最近工作中遇到需要調用別人的動態鏈接庫,但是隻有個dll文件,別的一概沒有,這可怎麼辦呢。還有不少dll導出的都是類,直接顯式調用不太方便,最後綜合網上的辦法,自己再寫兩個工具,終於實現了將dll導出lib文件,並同時生成.h頭文件。
還是自己動手才能豐衣足食啊。
=========================================================================
問題:如果手上只有一個DLL文件,沒有lib文件.h頭文件,程序裏怎麼調用它
方法當然很簡單,
先用VC的工具Depends.exe查看導出函數的函數名啊
用IDAPro或者其他反彙編工具分析函數原型
再用API函數:LoadLibrary,GetProcAddress
完成!
但是……如果Dll導出的是一個個的類呢,這就稍微有點麻煩
========================================================================
方法1:還是用顯式調用,LoadLibrary,GetProcAddress,
這時候就要在頭文件裏聲明一個個的“類成員函數的函數指針”了,
把GetProcAddress返回值賦給這些指針,使用時調用指針即可。
如何知道類的成員函數原型是長什麼樣的呢?
還是Depends工具,如果直接看,會發現導出函數名中有好多"?","@"等符號,
Depends的上面有個按鈕"C++"(如果沒有這個按鈕,說明你的Depends太老了,下載個新的吧),點了這個按鈕,再看看函數名有啥變化,是不是變得比較好理解了
不過Depends解析得還不夠完全,看不出來成員函數是public、protected還是private,也不知道調用約定是__cdecl、__stdcall還是__fastcall,是虛函數還是靜態成員函數。
如果要知道這些,還是用VC的undname.exe看得比較全面。
=======================================================================
方法2:用lib文件進行隱式鏈接,這樣無需LoadLibrary,個人感覺比較方便的
如何生成lib文件呢,假設動態鏈接庫名爲example.dll,步驟如下
1、執行dumpbin.exe/EXPORTS example.dll>example.def
生成了一個def文件,裏面的內容大概是下面這樣:
ordinal hint RVA name
1 0 00004570?function1@@
2 1 00004540?function2@@
2、編輯這個def文件,刪掉沒用的信息,將它整理成這樣的格式 :
LIBRARY "example"
EXPORTS
?function1@@ @1
?function2@@ @2
上面的@1和@2是根據第1個步驟中的ordinal序號來的
這個步驟我寫了個程序HandleDef.exe來自動修改,否則太多函數的話手動改就累死了
3、運行lib.exe/def:example.def
生成了example.lib和example.exp文件。這個lib文件就可以在VC裏用了,
比如這樣 #pragma comment(lib,"example.lib")
4、新建一個文件example.tmp,裏面保存函數名
?function1@@
?function2@@
然後運行undname.exeexample.tmp>example.txt
這樣函數名就解析到example.txt文件裏了
5、自己寫了個HandleTxt.exe程序,把example.txt轉換爲example.h
轉換後變成類似下面這樣:
1. class __declspec(dllimport) CExample
2. {
3. public: int function1(void);
4. public: void function2(char);
5. };
這個樣子的基本就能直接拷到VC裏用了。
不過,如果自己的程序要用到構造函數來新建一個對象的話,對導入類進行聲明的時候要事先分析好類對象的內存分佈(這可不是個簡單的事啊),上面這個CExample類應該這樣聲明
1. class __declspec(dllimport) CExample
2. {
3. public: int function1(void);
4. public: void function2(char);
5. public: BYTE m_data[256];
6. };
//上面m_data具體多少個字節,要靠自己反彙編分析,沒法自動生成,具體方法比較麻煩,有興趣的可以去網上查一些C++類的反彙編資料。
==========================================
總結:
爲了方便,把以下內容寫到一個批處理文件中
set name=example
dumpbin.exe/EXPORTS %name%.dll>%name%.def
HandleDef.exe %name%.def
lib.exe /def:%name%.def /MACHINE:IX86
undname.exe %name%.tmp>%name%.txt
HandleTxt.exe %name%.txt
執行完之後生成lib文件和h文件。
=========================================
上面提到的HandleDef.exe和HandleTxt.exe是我自己用C#寫的小程序。
寫了這麼多,也不知道有沒有人會感興趣。
注:我這個還只是適用於VC編寫的dll導出的類
如果用extern"c"導出的函數,除了自己反彙編分析原型,貌似沒有別的辦法
如何調用非VC編譯器編譯出來的類,暫時未研究過。
下載地址:http://pan.baidu.com/netdisk/singlepublic?fid=795627_2574562052