主程式呼叫 DLL 匯出工廠函式取得類實例指標,調用成員函式時連結器報錯:unresolved external symbol "public: void __thiscall ClassA::M(void)"。
ClassA::M() 定義在 DLL 內部,但類定義本身未匯出。extern "C" 僅適用於自由函式,C++ 類成員函式有 Name Mangling,無法直接用 GetProcAddress 取得。標頭檔:
#pragma once
#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
class DLL_API ClassA {
public:
void M();
};
DLL 專案定義 DLL_EXPORTS 巨集。主程式直接 #include 標頭檔,連結 .lib 匯入庫,像呼叫本地類一樣使用:
ClassA obj; // 或 new ClassA
obj.M();
DLL 僅匯出 extern "C" 自由函式,隱藏 C++ 類細節:
// DLL 標頭檔
#ifdef __cplusplus
extern "C" {
#endif
typedef struct ClassA_Opaque* ClassA_Handle;
__declspec(dllexport) ClassA_Handle ClassA_Create();
__declspec(dllexport) void ClassA_M(ClassA_Handle h);
__declspec(dllexport) void ClassA_Destroy(ClassA_Handle h);
#ifdef __cplusplus
}
#endif
DLL 實現:
// DLL cpp
struct ClassA_Opaque { void M() { cout << "I am invoked."; } };
extern "C" {
__declspec(dllexport) ClassA_Handle ClassA_Create() { return new ClassA_Opaque; }
__declspec(dllexport) void ClassA_M(ClassA_Handle h) { static_cast<ClassA_Opaque*>(h)->M(); }
__declspec(dllexport) void ClassA_Destroy(ClassA_Handle h) { delete static_cast<ClassA_Opaque*>(h); }
}
主程式動態載入:
auto hmod = LoadLibrary("DllProj.dll");
auto create = (ClassA_Handle(*)())GetProcAddress(hmod, "ClassA_Create");
auto callM = (void(*)(ClassA_Handle))GetProcAddress(hmod, "ClassA_M");
auto destroy = (void(*)(ClassA_Handle))GetProcAddress(hmod, "ClassA_Destroy");
ClassA_Handle h = create();
callM(h);
destroy(h);
FreeLibrary(hmod);