1

I've been trying to create a DLL and link the DLL to my program but every time I try my program can't find the function. The DLL loads fine but the function cant be found.

Program:

#include <iostream>
#include <windows.h>
using namespace std;

typedef void (*HelloPtr)();

int main() { 
    HelloPtr hello;
    HINSTANCE hDll = LoadLibrary("dll.dll");
    if(hDll)
    {
        hello = (HelloPtr)GetProcAddress(hDll, "hello");
        if(hello) {
            hello();
        } else {
            // Error code here
        }
    }
    return 0;   
}

dllmain.cpp

#include "dll.h"
#include <windows.h>

DLLIMPORT void hello()
{
   MessageBox(NULL, "Hey", "", MB_OK);          
}

DllClass::DllClass()
{

}

DllClass::~DllClass ()
{

}


BOOL APIENTRY DllMain (HINSTANCE hInst     /* Library instance handle. */ ,
                       DWORD reason        /* Reason this function is being called. */ ,
                       LPVOID reserved     /* Not used. */ )
{
    switch (reason)
    {
        case DLL_PROCESS_ATTACH:
        break;

        case DLL_PROCESS_DETACH:
        break;

        case DLL_THREAD_ATTACH:
        break;

        case DLL_THREAD_DETACH:
        break;
    }

    /* Returns TRUE on success, FALSE on failure */
    return TRUE;
}

dll.h

#ifndef _DLL_H_
#define _DLL_H_

#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport) void hello(void)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllexport) void hello(void)
#endif /* Not BUILDING_DLL */

class DLLIMPORT DllClass
{
    public:
    DllClass();
    virtual ~DllClass(void);

    // Says hello world
    DLLImport void hello(void);

    private:

};


#endif /* _DLL_H_ */

I'd like to know what I'm doing wrong so I can document it and learn.

Thanks

Jack Harvin
  • 5,885
  • 7
  • 21
  • 21

4 Answers4

1

You need to put your DLL code in an extern "C" block, otherwise the compiler will mangle the names of all functions.

Take a look at this question for further info: C++ DLL Export: Decorated/Mangled names

Community
  • 1
  • 1
Jon
  • 396,160
  • 71
  • 697
  • 768
  • And to see this easily for yourself, use [Dependency Walker](http://www.dependencywalker.com/) on your DLL. It will show you all of the exports. – kichik Nov 28 '10 at 11:18
0

In dll put all functions you want export into

    #ifdef __cplusplus
    extern "C" {
    #endif

   DLLIMPORT void hello()
   {
   MessageBox(NULL, "Hey", "", MB_OK);          
   }

    #ifdef __cplusplus
    } 
    #endif
Sanja Melnichuk
  • 3,387
  • 3
  • 23
  • 46
0

Function names are mangled when exported, for obvious reasons. What if you are using function overloading? What if you have a function named hello() in two different classes? For example, Qt's QString& remove(const QRegExp& rx) is exported as ?remove@QString@@QAEAAV1@ABVQRegExp@@@Z. The easiest way to work around this is to export your functions using extern "C" and cdecl or stdcall so they are not mangled (or mangled in a more standard/predictable manner).

wj32
  • 7,387
  • 2
  • 25
  • 35
0

You have:

#if BUILDING_DLL
# define DLLIMPORT __declspec (dllexport) void hello(void)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec (dllexport) void hello(void)
#endif /* Not BUILDING_DLL */

Then you have:

DLLIMPORT void hello()

The combination will turn into this, which doesn't make sense:

__declspec (dllexport) void hello(void) void hello()

Change your DLLIMPORT macro to this instead:

#if BUILDING_DLL
# define DLLIMPORT __declspec(dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec(dllimport)
#endif /* Not BUILDING_DLL */

EDIT: You also have dllexport for both cases; the lower should be dllimport.

You've also used DLLImport rather than DLLIMPORT on the hello method.

You also cannot (or at least should not) export a non-static class member in a DLL. If you want to export C++ classes I would recommend either:

  1. Export DLL functions which create, destroy and call methods on your class objects. The creation functions would return something like a HANDLE, void* or similar opaque pointer. The other methods would take that as an argument, cast it to what it really is and then call the method on it.

  2. Use COM.

You should also follow Sanja Melnichuk's advice to avoid your exported function names being decorated.

Here is an example Dll.h:

#ifndef _DLL_H_
#define _DLL_H_

#if BUILDING_DLL
# define DLLIMPORT __declspec(dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec(dllimport)
#endif /* Not BUILDING_DLL */


extern "C"
{
    DLLIMPORT void hello(void);
}

Note that DllClass is gone. (Your hello function within dllmain.cpp is unchanged since it never specified it was part of DllClass in the first place.)

Don't forget to define BUILDING_DLL in the DLL project and ensure you do NOT define it in the project which tries to load the DLL.

Leo Davidson
  • 5,785
  • 1
  • 25
  • 29
  • It works. Thank you. Could I ask, where is the best place to read up about this, more in depth? There are a lot of tutorials online but the one's I've seen don't explain much. Maybe I'm searching for the wrong keywords. Thanks. – Jack Harvin Nov 28 '10 at 12:48
  • Not sure where I learned about making DLLs. Probably a combination of looking at existing one and stuff on CodeProject. – Leo Davidson Nov 28 '10 at 13:12
  • @Jack Harvin: BTW, please accept the answer if it solved things for you. – Leo Davidson Nov 28 '10 at 22:27