DLL ,我想大家都不陌生
不管你是否搞程設的,都一定對它有印象(某遊戲出現錯誤之類)
這次就來了解一下
我挑著重點說,其他說明還是參考最底下的連結吧!他們寫的比較好~
(以下大多是引用)
DLL的存在有何意義?
1 、 有 效 率 的 重 複 使 用 程 式 碼
2 、 區 分 程 式 碼
3 、 節 省 記 憶 體 的 使 用 量
4 、 將 程 式 推 向 國 際 舞 台
而程設人員常聽到的COM(Component Object Model),則是 DLL 的擴充(進階)使用
這兩者都牽扯到程設新手困惑的名詞之一「介面(Interface)或稱為虛擬繼承」
由於是共用記憶體,又會牽扯到一個名詞「相 對 虛 擬 位 址 (Relative Virtual Address ,RVA) 」
會特別強調這點,是因為我犯下一個很蠢的舉動,後面會說
DLL產生的同時會伴有一個對應的LIB檔
要給別人用的的程式,需要作輸出(Export)的動作,反之需要作輸入(Import)的動作
OK!讀萬卷書不如行萬里路!就來做出一個DLL來吧!
1 、 開啟DLL專案,以VC8.0為例
「檔案 > 新增 > 專案 > Visual C++ > Win32 > Win32專案 > 應用程式類型 > DLL > 完成!」
2 、 console 和 window 都有城市的進入點 main() 和 WinMain()
DLL的進入點則為 DLLMain()
3 、 輸出,再需要輸出的函式前面加上「__declspec(dllexport)」即可,例如:
__declspec(dllexport) void Function(void); |
也可以輸出一個類別(Class)
class __declspec(dllexport) MyClass : public BaseClass{ … …}; |
當然別忘記要實作這些函數啊!
做個簡單的範例:
#include <iostream> #include <Windows.h> using namespace std; // 先宣告函式 // 進入點 // 實作函式 int WhoSmall(int a, int b) |
嗯!編譯無誤之後就可以得到DLL和LIB了!
接著來看看如
使用~
使用該DLL裡面的函式可分為兩大類:
1 、 隱式連結(Implicitly Link)
1 、 靜態載入方式所使用到的這個DLL會在應用程式執行時載入
然後就可以呼叫出所有由DLL中匯出的函式
就好像是包含在程式中一般。
2 、 動作較為簡單,載入的方法由編譯器負責處理,咱們不須動腦筋。
缺點:
這個程式在開始時就出現無法找到DLL的訊息而 導致應用程式無執行。
2 、 編譯時需要加入額外的import library。
3 、 若是要載入的DLLs一多,載入應用程式的速度會便慢。
4 、 若遇到不同品牌 的C++編譯器時
靜態載入可就沒有這麼簡單處理了
因為當函式經過Calling Conventions的處理後
若要使用其他品牌編譯器所致造出的DLL須得大動干戈才行。
2 、 顯式連結(Explicit Linking)
優點:
1 、DLL只要需要時才會載入到記憶體中
可以更有效的使用記憶體。
2 、 應用程式載入的速度較使用隱式鏈結時快
因為當程式開始載入時並不需要把DLL給載入到行程中。
3 、 編譯時不須額外的import library檔。
4 、 讓我們可以更清楚DLL的載入流程。
缺點:
就是得要自行連結,自然要多點code囉!
靜態連結範例
1 、連結 lib
可以使用 #program 指令連結,或者編譯器連結
2 、宣告
export 時使用…
__declspec(dllexport) int WhoBig(int a, int b);
import時…
__declspec(dllimport) int WhoBig(int a, int b);
3 、放置DLL
把 test.dll 放在適當的地方就大功告成了!
之後就可以當一般函式使用了~
// 連結 lib #pragma commment(lib, "test.dll"); // 宣告 __declspec(dllexport) int WhoSmall(int a, int b); // …任意使用 |
小技巧
如果每次更改都要對 import / export 分別修改,那豈不煩死人?
// test.h #ifdef DLL_EXPORT #define DLLACT __declspec(dllexport) #else #define DLLACT __declspec(dllimport) #endif // 宣告 DLLACT int WhoSmall(int a, int b); |
聰明的你應該看出來了吧!
在製作dll的時候也只要在 include 這個 .h 檔之前定義 DLL_EXPORT 就可以了!
(DLL_EXPORT 這個名稱隨便你設)
一般使用者也一樣 inlude ,連結 lib 就可以使用,方便吧?
Name Mangling
似乎沒有一個正式的翻譯?總之就是針對函數名稱做點處理的意思!
在不同編譯器底下,處理出來的結果都不同,這就是隱式連結的缺點之一
例如:
int Func(float X);
void Func(double *d);
使用 C++Builder 3.0 所編譯出來的函式名稱為:
@Func$qf
@Func$qi
@Func$qpd
而使用 Visual C++ 6.0 所編譯出來的函式名稱為:
?Func@@YAHH@Z
?Func@@YAHM@Z
?Func@@YAXPAN@Z
這麼做主要是因為C++提供了多載(overload)
以往C風格的處理方式就不敷使用了!
當然,我們可以抑制 Name Mangling
在需要輸出的函式前面加上 extern "C" 即可
例如:
extern "C" __declspec(dllexport) int WhoBig(int a, int b); |
參考:
DLL(Dynamic Linkable Library)
基于Visual C++6.0的DLL编程实现
Win32 DLL
探 訪 動 態 連 結 函 式 庫 (Dynamic Linking Libraries,DLLs)
什么是 DLL?