我大部分的C/C++開發包括單片模塊文件和任何絕對沒有課,所以通常當我需要做一個DLL與使用的功能我只是用標準__declspec(dllexport)
指令導出它們。然後通過LoadLibrary()
或在編譯時使用頭文件和lib文件動態訪問它們。從DLL導出C++類
當你想導出整個類(以及它的所有公共方法和屬性)時,你如何做到這一點?
是否有可能在運行時動態加載該類,如果有,如何?
你會怎麼做一個頭和lib編譯時鏈接?
我大部分的C/C++開發包括單片模塊文件和任何絕對沒有課,所以通常當我需要做一個DLL與使用的功能我只是用標準__declspec(dllexport)
指令導出它們。然後通過LoadLibrary()
或在編譯時使用頭文件和lib文件動態訪問它們。從DLL導出C++類
當你想導出整個類(以及它的所有公共方法和屬性)時,你如何做到這一點?
是否有可能在運行時動態加載該類,如果有,如何?
你會怎麼做一個頭和lib編譯時鏈接?
那麼遲綁定呢?如在加載 它與LoadLibrary()和 GetProcAddress()?我使用 可以在運行時加載庫,如果您可以在此處執行 ,它會很棒。
所以有兩種方法來加載DLL。首先是引用DLL中的一個或多個符號(例如,您的類名),提供相應的導入.LIB,並讓鏈接器將所有內容全部排除。
第二個是通過LoadLibrary顯式加載DLL。
這兩種方法都適用於C級功能導出。你可以讓鏈接器處理它,或者像你注意的那樣調用GetProcAddress。
但是,當涉及到輸出類時,通常只使用第一種方法,即隱式鏈接到DLL。在這種情況下,DLL在應用程序啓動時加載,如果找不到DLL,應用程序將無法加載。
如果你想鏈接到一個DLL中定義的類,並且希望該DLL動態加載,程序開始後的某個時候,你有兩個選擇:
使用創建的類的對象一個特殊的工廠功能,內部將不得不使用(一點點)彙編程序將新創建的對象「連接」到適當的偏移處。這必須在加載DLL後的運行時完成,顯然。這種方法的一個很好的解釋可以找到here。
所有事情都考慮過......可能更好的方法是使用隱式鏈接,在這種情況下,您肯定希望使用上面顯示的預處理器技術。事實上,如果您在Visual Studio中創建一個新DLL並選擇「導出符號」選項,則會爲您創建這些宏。
好運...
我使用了一些宏來標記導入或導出代碼
#ifdef ISDLL #define DLL __declspec(dllexport) #endif #ifdef USEDLL #define DLL __declspec(dllimport) #endif
然後聲明類頭文件:
class DLL MyClassToExport { ... }
然後在libary #define ISDLL
,並USEDLL
包括前頭文件在你想使用該類的地方。
我不知道,如果你可能需要用LoadLibrary
工作當你建立動態連接庫,將使用DLL模塊做不同的事情,有某種的#define,你可以用它來的一個與其他區分,那麼你可以做這樣的事情在你的類的頭文件:
#if defined(BUILD_DLL)
#define IMPORT_EXPORT __declspec(dllexport)
#else
#define IMPORT_EXPORT __declspec(dllimport)
#endif
class IMPORT_EXPORT MyClass {
...
};
編輯:crashmstr打我吧!
如果你願意把你導出類虛函數表,你可以導出返回的接口函數,實現.dll文件的類,然後把在.def文件中。你可能不得不做一些聲明欺騙,但它不應該太難。
就像COM一樣。 :)
最近我問自己完全一樣的問題,並總結我的發現in a blog post。你可能會覺得它很有用。它涵蓋了從DLL導出C++類,並且使用LoadLibrary
動態加載它們,並討論了其中的一些問題,如內存管理,名稱修改和調用約定。
添加一個簡單的工作示例從一個DLL導出一個C++類:
例如下面給出的只給你的DLL和EXE如何相互影響(言自明)一個簡短的概述,但它需要更多的東西添加以更改爲生產代碼。
全部樣品實例在分爲兩個部分
A.創建一個.dll庫(MYDLL.DLL)
B.創建其使用的.dll庫(應用程序)的應用程序。
A.的.dll項目文件(MYDLL.DLL):
1 dllHeader.h
#ifdef MYDLL_EXPORTS
#define DLLCALL __declspec(dllexport) /* Should be enabled before compiling
.dll project for creating .dll*/
#else
#define DLLCALL __declspec(dllimport) /* Should be enabled in Application side
for using already created .dll*/
#endif
// Interface Class
class ImyMath {
public:
virtual ~ImyMath() {;}
virtual int Add(int a, int b) = 0;
virtual int Subtract(int a, int b) = 0;
};
// Concrete Class
class MyMath: public ImyMath {
public:
MyMath() {}
int Add(int a, int b);
int Subtract(int a, int b);
int a,b;
};
// Factory function that will return the new object instance. (Only function
// should be declared with DLLCALL)
extern "C" /*Important for avoiding Name decoration*/
{
DLLCALL ImyMath* _cdecl CreateMathObject();
};
// Function Pointer Declaration of CreateMathObject() [Entry Point Function]
typedef ImyMath* (*CREATE_MATH)();
2. dllSrc.cpp
#include "dllHeader.h"
// Create Object
DLLCALL ImyMath* _cdecl CreateMathObject() {
return new MyMath();
}
int MyMath::Add(int a, int b) {
return a+b;
}
int MyMath::Subtract(int a, int b) {
return a-b;
}
B.應用程序Pr選擇哪個負載並鏈接已經創建的。dll文件:
#include <iostream>
#include <windows.h>
#include "dllHeader.h"
int main()
{
HINSTANCE hDLL = LoadLibrary(L"MyDLL.dll"); // L".\Debug\MyDLL.dll"
if (hDLL == NULL) {
std::cout << "Failed to load library.\n";
}
else {
CREATE_MATH pEntryFunction = (CREATE_MATH)GetProcAddress(hDLL,"CreateMathObject");
ImyMath* pMath = pEntryFunction();
if (pMath) {
std::cout << "10+10=" << pMath->Add(10, 10) << std::endl;
std::cout << "50-10=" << pMath->Subtract(50, 10) << std::endl;
}
FreeLibrary(hDLL);
}
std::cin.get();
return 0;
}
一個很好的答案寫後:http://stackoverflow.com/a/22797419/1995714 – 2016-08-25 19:21:39