Hi All,
I'm having trouble with my code.
When I compile I get Undefined reference to class::method where by class and method are my class and method. I get my methods from akrip32.dll

I,m at work so I have no source files, but I will attach them later when I lay hold on them.
Thanks all :)

EDIT: I use MINGW that comes with Codeblocks 8.02

Dani AI

Generated

A concise recap and some extra checks that clarify why the link/ runtime issues happened and how to avoid similar problems in future.

The original build error was caused by a few separate problems that masked each other: a local object with the same name as the function (hiding the function call), a mismatched function invocation (passing a parameter where the declared function took none), and—most importantly for the runtime crash—passing an uninitialized pointer into a DLL routine. An uninitialized pointer contains garbage; if the DLL writes into that address the result is undefined behavior and usually an immediate crash. Thanks to for spotting the naming/return issues and to for showing that the function expects the address of a real struct instance.

Practical rules to follow:

  • Allocate an actual CDLIST struct (stack or heap) and initialize it (zeroing is a safe start) before passing its address to the DLL function. Only read fields after the function returns success.
  • Verify the exact function signature and calling convention exported by the DLL. A calling-convention mismatch (cdecl vs stdcall) will corrupt the stack and can crash even if pointers are correct. For example, a DLL exported with WINAPI/__stdcall requires the same in the function-pointer type.
    // example of matching stdcall (use windows.h for WINAPI)
    typedef int (WINAPI *GetCDList_t)(CDLIST* pList);
  • If the DLL uses C++ exports, name-mangling will change the exported name; prefer C exports (extern "C") or link via an import library rather than guessing names.

Debug checklist: enable high warning levels (-Wall -Wextra), build a debug binary (-g, -O0), step into the call with a debugger, inspect pointer values before the call, and confirm app/DLL bitness match (32/64-bit). Also confirm who owns any memory returned by the DLL and avoid FreeLibrary while that memory is still needed. These steps explain the crash seen after the DLL loaded and will prevent similar problems in other DLL-interfacing code.

Recommended Answers

All 14 Replies

The project is probably not linking with the library that is produced for that dll, most likely akrip32.lib, or libakrip32.a, or something like that.

commented: You helped me alot! +4

Errors I get are as below and I have attached the Source code and DLL (the DLL is LGPLed)
C:\Program Files\CodeBlocks\Projects\testingAkrip\main.cpp||In member function `DWORD CDRip::GetVersion()':|
C:\Program Files\CodeBlocks\Projects\testingAkrip\main.cpp|38|warning: control reaches end of non-void function|
C:\Program Files\CodeBlocks\Projects\testingAkrip\main.cpp||In function `int GetCDLists()':|
C:\Program Files\CodeBlocks\Projects\testingAkrip\main.cpp|70|warning: control reaches end of non-void function|
C:\Program Files\CodeBlocks\Projects\testingAkrip\main.cpp|57|warning: 'lpcd' might be used uninitialized in this function|
obj\Release\app.o:app.cpp:(.text+0x2c)||undefined reference to `CDRip::GetCDLists(CDLIST*)'|
||=== Build finished: 1 errors, 3 warnings ===|

In function GetCDLists() (main.cpp) you have an object also named GetCDLists. Rename that object to something else, such as GList, or whatever. Just don't give it the same name as the function name.

Then a little later in that function you attempt to call the function with a parameter. That function does not take any parameters.


CDRip::GetVersion: you have to put a return value at the end of that function.

Thanks alot.
I'm working on your comments :)

Here is the updated code.
When I run the app, it just loads the DLL then crashes :(
I don't understand what I do wrong. BTW I'm just starting with Windows DLL and I want to implement simple ripping function of the Akrip32.dll

Probably because you are passing uninitialized variables to functions. If your compiler didn't produce these warnings then use a different compiler.

1>c:\dvlp\test9\test9\main.cpp(59) : warning C4700: uninitialized local variable 'lpcd' used
1>c:\dvlp\test9\test9\app.cpp(16) : warning C4700: uninitialized local variable 'lister' used

it didnt!
I use GCC compiler that comes with Code::Blocks. may be I should change compiler to windows

windows is not a compiler -- its an operating system. IMHO vc++ 2008 Express is one of the best compilers/IDEs available today. It produces a lot of errors and warnings that other compilers completly miss. And its debugging facilities can't be beat by any other IDE/compiler on any operating system.

Instead of changing compilers at this point, find out how to increase the warning level so that it will produce better errors and warnings.

LPCDLIST is pointer to struct.
GetCDLists code :

if (GCDLists !=0){
        LPCDLIST lpcd;  // Pointer to struct
        GCDLists(lpcd); //  <-- no place for data
  .....
if (GCDLists !=0){
            CDLIST lp;         // struct variable
            GCDLists(&lp);  //  an address of struct 
            std::cout <<   lp.cd[0].info.vendor;
 .....
commented: You saved me alot of pain! +4

LPCDLIST is pointer to struct.
GetCDLists code :

if (GCDLists !=0){
        LPCDLIST lpcd;  // Pointer to struct
        GCDLists(lpcd); //  <-- no place for data
  .....
if (GCDLists !=0){
            CDLIST lp;         // struct variable
            GCDLists(&lp);  //  an address of struct 
            std::cout <<   lp.cd[0].info.vendor;
 .....

That completely solved the Problem.
Thanks you two guys :) You have saved me alot of pains

Ok, your code works, but I have not understood the changes you made. Can you explain a little bit of changes and what I was doing wrong. Also why Did you changed LPCDLIST lpcd; to GCDLists(&lp); ?? also what about std::cout << [0].info.vendor; ??

Thanks

app.cpp

# include "main.h"
#include <iostream>
//testing function below

//main application
int main()
{
    CDRip instance;
    //DWORD ver = instance.GetVersion();
    //Get Version
    //std::cout<<"The Version is: "<<ver<<std::endl;
    //Get CDList
    CDLIST lister;   // object of CDLIST struct

    instance.GetCDLists(&lister);  // Pass an address of lister 
    return 0;
}

main.cpp

....
int CDRip::GetCDLists(LPCDLIST lpcd){
    //define a pointer to the function
    typedef int (*ptrGetCDLists)(LPCDLIST lpcd);
    //Create a pointer function to access the DLL function
    ptrGetCDLists GCDLists;

    //Load the DLL
    HINSTANCE hDLL = LoadLibrary("akrip32.dll");
    //DLL loaded successful?
    if (hDLL!=0){
        std::cout<<"Loaded DLL"<<std::endl;
        //Get Function address
        GCDLists = (ptrGetCDLists)GetProcAddress(hDLL, "GetCDList");
        // Function loaded Succesful?
        if (GCDLists !=0){
            GCDLists(lpcd);
            std::cout <<   lpcd->cd[0].info.vendor;
            FreeLibrary(hDLL);
        }
        // Function Loading failed?
        else{
            std::cout<<"Error, can't load function GetVersion!"<<std::endl;
            FreeLibrary(hDLL);
        }
    }
    //DLL Loading failed
    else std::cout<<"Error! Cannot Load Library"<<std::endl;
    return 0;
}
...
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.