[英]Dynamic Linking C++ DLL … What am I doing wrong?
我一直在嘗試創建一個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文件
#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_ */
我想知道我在做錯什么,所以我可以記錄下來並學習。
謝謝
您需要將DLL代碼放在extern "C"
塊中,否則編譯器將破壞所有函數的名稱 。
看看這個問題以獲取更多信息: C ++ DLL導出:裝飾/拼寫的名稱
在dll中,將要導出的所有功能放到
#ifdef __cplusplus
extern "C" {
#endif
DLLIMPORT void hello()
{
MessageBox(NULL, "Hey", "", MB_OK);
}
#ifdef __cplusplus
}
#endif
出於明顯的原因,函數名稱在導出時會被篡改 。 如果使用函數重載怎么辦? 如果您在兩個不同的類中都有一個名為hello()
的函數,該怎么辦? 例如,Qt的QString& remove(const QRegExp& rx)
導出為?remove@QString@@QAEAAV1@ABVQRegExp@@@Z
解決此問題的最簡單方法是使用extern "C"
和cdecl或stdcall導出函數,以使它們不被破壞(或以更標准/可預測的方式被破壞)。
你有:
#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的項目中定義它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.