在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