Dynamic Linking C++ DLL ... What am I doing wrong?
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 开发者_Go百科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
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
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
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).
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:
- 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. 
- 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.
 
         加载中,请稍侯......
 加载中,请稍侯......
      
精彩评论