我使用过“CPPLoadLibrary”示例(来自Microsoft All-in-One框架) 好的,样本DLL中有两种导出符号的方法。
所以我们有以下代码。
typedef int (_cdecl* LPFNGETSTRINGLENGTH1) (PCWSTR);
typedef int (CALLBACK* LPFNGETSTRINGLENGTH2) (PCWSTR);
LPFNGETSTRINGLENGTH1 lpfnGetStringLength1 = (LPFNGETSTRINGLENGTH1)
GetProcAddress(hModule, "GetStringLength1");
LPFNGETSTRINGLENGTH2 lpfnGetStringLength2 = (LPFNGETSTRINGLENGTH2)
GetProcAddress(hModule, "_GetStringLength2@4");
所以我的问题是如何确定符号的名称以便调用GetProcAddress? 在第一种情况下,它非常简单,我们从.DEF文件中获取该符号名称。 但是“_GetStringLength2 @ 4”怎么样? 什么是下划线?什么是“@ 4”代表什么? 感谢。
答案 0 :(得分:2)
如果不使用.DEF文件,则根据调用约定修改导出名称,以支持导出重载函数。见Why can't I GetProcAddress a function I dllexport'ed?:
[T]装饰方案因建筑而异,从调用约定到调用约定。因此,例如,如果函数是从PPC DLL导出的,则必须执行
GetProcAddress(hinst, "..SomeFunction")
,但如果它是作为extern "C" __stdcall
从80386 DLL导出的,则需要GetProcAddress(hinst, "_SomeFunction@8")
,但如果是__fastcall
,则需要GetProcAddress(hinst, "@SomeFunction@8")
。此外,C ++装饰因编译器供应商而异。如果使用Microsoft C ++编译器编译,则C ++导出的函数可能需要
GetProcAddress(hinst, "?SomeFunction@@YGXHH@Z")
,但如果使用Borland C ++编译器进行编译,则可能需要一些其他修饰的字符串。因此,如果您希望人们能够
GetProcAddress
获取函数,并且您希望您的代码可以移植到多个平台,或者您希望它们能够使用C / C以外的语言来使用您的DLL C ++或使用与Microsoft Visual Studio不同的C ++编译器,然后必须通过其未修饰的名称导出该函数。
有关各种名称装饰方案的说明,请参阅The history of calling conventions, part3。在这种情况下,该函数使用__stdcall
调用约定,因此它通过在下划线前加上@
符号以及所需参数的字节数来进行修饰。它需要一个字大小的参数,总共4个字节,所以它被装饰为_GetStringLength2@4
。
答案 1 :(得分:0)
要回答您的实际问题,请使用编译器的TDUMP或类似工具,或任何其他可显示可执行文件导出表的工具,以便查看实际导出的名称。