在C++中,為了允許操作符重載和函數重載,C++編譯器往往按照某種規則改寫每一個入口點的符號名,以便使用同一個名字(具有不同的參數類型或者是不同的作用域)有多種不同的用法,而不會打破現有基于C的鏈接器,.這項技術通常被稱為改編(Name Mangling)或者名稱修飾(Name Decoration),許多C++編譯器廠商選擇了自己的名稱修飾方案.
在VC++中,函數修飾名有編譯類型(C或C++),函數名,類名,調用約定,返回類型,參數等多種因素決定.關于名稱修飾的東西很多,下面僅僅簡單的談一下常用的C編譯,C++編譯函數名修飾
一.C編譯時函數名修飾約定規則
(1)_stdcall調用約定在輸出函數名前面加上一個下劃線前綴,后面加上一個"@"符號和其參數字節數,格式_functionname@number
(2)_cedecl調用約定僅在輸出函數名稱前加上一個下劃線的前綴,格式為_functionname
(3)_fastcall調用約定在輸出函數名前面加上一個"@",后面加上一個"@"和參數字節數,格式@functionname@number
二.C++編譯時函數名修飾約定規則
(1)_stdcall調用約定以"?"標識函數名的開始,后面跟函數名;函數名后以"@@YG"標識參數表的開始,后跟參數表;參數表的第一項為該函數的返回值類型,其后一次為參數的數據類型,指針標識在其所指數據類型前;參數表后以"@Z"標識整個名字結束,如果該函數無參數,則以為"Z"標識結尾.其格式為: "?functionname@@YG*****@Z"或者"?functionname@@YG*XZ"
(2)_cdecl調用約定同上面的_stdcall,只是參數表的開始由上面的@@YG變成了@@YA
(3)_fastcall調用約定規則同上_stdcall,只是參數表由"@@YG"變成了"@@YI"
--------------------------------------------------------------------------------------------------------------------------
從dll導出lib文件
一、使用VC++的工具DUMPBIN將DLL中的導出函數表導出到一定義(.DEF)文件
EXAMPLE:
DUMPBIN SkinH.dll /EXPORTS /OUT:SkinH.def
Dump of file G:\Programing\VC6.0\Test123\SkinH.dll
File Type: DLL
? Section contains the following exports for SkinH_VB6.dll
?????????? 0 characteristics
??? 4AAEFE79 time date stamp Tue Sep 15 10:39:53 2009
??????? 0.00 version
?????????? 1 ordinal base
????????? 23 number of functions
????????? 23 number of names
??? ordinal hint RVA????? name
????????? 1??? 0 00025FF0 SkinH_AdjustAero
????????? 2??? 1 00025FC0 SkinH_AdjustHSV
????????? 3??? 2 00025F00 SkinH_Attach
????????? 4??? 3 00025F10 SkinH_AttachEx
????????? 5??? 4 00025F30 SkinH_AttachExt
????????? 6??? 5 00025F60 SkinH_AttachRes
????????? 7??? 6 00025F90 SkinH_AttachResEx
????????? 8??? 7 000260A0 SkinH_Detach
????????? 9??? 8 000260B0 SkinH_DetachEx
???????? 10??? 9 000260C0 SkinH_GetColor
???????? 11??? A 00026060 SkinH_LockUpdate
???????? 12??? B 00026080 SkinH_Map
???????? 13??? C 00026130 SkinH_NineBlt
???????? 14??? D 00025FE0 SkinH_SetAero
???????? 15??? E 000261D0 SkinH_SetBackColor
???????? 16??? F 00026160 SkinH_SetFont
???????? 17?? 10 00026180 SkinH_SetFontEx
???????? 18?? 11 000261F0 SkinH_SetForeColor
???????? 19?? 12 00026030 SkinH_SetMenuAlpha
???????? 20?? 13 00026100 SkinH_SetTitleMenuBar
???????? 21?? 14 00026040 SkinH_SetWindowAlpha
???????? 22?? 15 000260E0 SkinH_SetWindowMovable
???????? 23?? 16 00026210 SkinH_VerifySign
? Summary
?????? 1D000 .52PoJie
?????? 39000 .Hmily
1)添加LIB說明 LIBRARY "SkinH"??????????? ;DLL名稱
DESCRIPTION "SkinH library"?
2)去掉導出函數說明端以外的內容,在LIB說明下添加 "EXPROTS" 說明導出函數
3)將所有的函數放至行首,去掉 "hint" 和 "RVA" 數據,留下函數的序號 "ordinal" ,在序號前加上 "@" 符號 形成 "_導出函數名@參數字節和 @序號" 此種格式(__stdcall 方式調用導出的函數符號是 "函數名稱@參數字節和"). 最后形成.DEF文件如下:
LIBRARY "SkinH"
DESCRIPTION "SkinH_VB6 library"
EXPORTS
SkinH_AdjustAero@0?@1
SkinH_AdjustHSV@0?@2
SkinH_Attach@0?@3
SkinH_AttachEx@8?@4
SkinH_AttachExt@0?@5
SkinH_AttachRes@0?@6
SkinH_AttachResEx@0?@7
SkinH_Detach@0?@8
SkinH_DetachEx@0?@9
SkinH_GetColor@0?@10
SkinH_LockUpdate@0?@11
SkinH_Map@0?@12
SkinH_NineBlt@0?@13
SkinH_SetAero@4?@14
SkinH_SetBackColor@0?@15
SkinH_SetFont@0?@16
SkinH_SetFontEx@0?@17
SkinH_SetForeColor@0?@18
SkinH_SetMenuAlpha@0?@19
SkinH_SetTitleMenuBar@0?@20
SkinH_SetWindowAlpha@8?@21
SkinH_SetWindowMovable@0?@22
SkinH_VerifySign@0?@23
當然 有的函數 我沒有用的? 我就全部給了0
4)使用VC++的LIB工具,帶/DEF:(.def文件名) /MACHINE:IX86(80X86機器),就輸出符合VC++格式的的LIB文件了.
EXAMPLE:LIB /DEF:SkinH.def /MACHINE:IX86
5)接時帶上LIB文件鏈接;注意的是當有些動態庫DUMPBIN的只有函數名,無"@nn"的參數格式,如C++Builder寫的DLL,輸出就只有函數名符號,鏈接時就會報錯: error LNK2002:unresolved external symbol "functionname@nn" 提示程序中引入的函數符號無法識別,這時只要將DEF文件中相應的函數名稱改為functionname@nn方式,重新建立 LIB,重新鏈接即可.
最后還有一句,要自動生成.h文件好象是不行的.因為dll里沒有保存函數原型,需要反匯編并分析代碼才知道每個函數的參數情況.
extern "C" BOOL WINAPI SkinH_AttachEx(LPCTSTR strSkin,LPCTSTR strPwd);
extern "C" BOOL WINAPI SkinH_SetWindowAlpha(HWND hWnd,DWORD nAlpha);
extern "C" BOOL WINAPI SkinH_SetAero(DWORD nEnable);
最后函數頭添加聲明?
就可以調用了 - -!
?
相關參考:
http://blog.sina.com.cn/s/blog_4c72efa6010092m5.html
http://blog.csdn.net/tingsking18/article/details/5394466
?
?