我一直在尝试创建一个DLL并将DLL链接到我的程序,但每次我尝试我的程序都找不到该功能。 DLL加载正常,但无法找到函数。
程序:
#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_ */
我想知道我做错了什么,所以我可以记录并学习。
由于
答案 0 :(得分:1)
您需要将DLL代码放在extern "C"
块中,否则编译器将mangle the names所有函数。
请查看此问题以获取更多信息: C++ DLL Export: Decorated/Mangled names
答案 1 :(得分:0)
在dll中将您要导出的所有功能放入
#ifdef __cplusplus
extern "C" {
#endif
DLLIMPORT void hello()
{
MessageBox(NULL, "Hey", "", MB_OK);
}
#ifdef __cplusplus
}
#endif
答案 2 :(得分:0)
导出时的函数名are mangled,原因很明显。如果您正在使用函数重载怎么办?如果在两个不同的类中有一个名为hello()
的函数,该怎么办?例如,Qt的QString& remove(const QRegExp& rx)
导出为?remove@QString@@QAEAAV1@ABVQRegExp@@@Z
。解决这个问题的最简单方法是使用extern "C"
和cdecl或stdcall导出函数,这样它们就不会被破坏(或以更标准/可预测的方式破坏)。
答案 3 :(得分:0)
你有:
#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 */
然后你有:
DLLIMPORT void hello()
组合会变成这个,这没有意义:
__declspec (dllexport) void hello(void) void hello()
将您的DLLIMPORT宏更改为:
#if BUILDING_DLL
# define DLLIMPORT __declspec(dllexport)
#else /* Not BUILDING_DLL */
# define DLLIMPORT __declspec(dllimport)
#endif /* Not BUILDING_DLL */
编辑:你也有两个案件的dllexport;较低的应该是dllimport。
你也在hello方法上使用了DLLImport而不是DLLIMPORT。
您也不能(或至少不应该)在DLL中导出非静态类成员。如果要导出C ++类,我建议:
导出DLL函数,用于在类对象上创建,销毁和调用方法。创建函数将返回类似HANDLE,void *或类似的不透明指针。其他方法将其作为一个参数,将其转换为它的实际内容,然后在其上调用该方法。
使用COM。
您还应该遵循Sanja Melnichuk的建议,以避免出口功能名称被修饰。
以下是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);
}
请注意,DllClass已经消失了。 (你的dllmain.cpp中的hello函数没有改变,因为它从来没有指定它首先是DllClass的一部分。)
不要忘记在DLL项目中定义BUILDING_DLL,并确保不要在试图加载DLL的项目中定义它。