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.
精彩评论