确定DLL的符号名称

时间:2013-10-02 17:00:13

标签: c++ winapi dll

我使用过“CPPLoadLibrary”示例(来自Microsoft All-in-One框架) 好的,样本DLL中有两种导出符号的方法。

  1. 使用.DEF文件从DLL导出符号 模块定义(.DEF)文件是包含一个或多个模块的文本文件 描述DLL的各种属性的语句。创建一个.DEF文件和 在构建DLL时使用.def文件。使用这种方法,我们可以导出 函数来自DLL的序数而不是名称。
  2. 使用__declspec(dllexport)从DLL导出符号 __declspec(dllexport)将导出指令添加到目标文件中,以便我们这样做 不需要使用.def文件。这种便利在尝试时最为明显 导出装饰的C ++函数名称。
  3. 所以我们有以下代码。

    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”代表什么? 感谢。

2 个答案:

答案 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或类似工具,或任何其他可显示可执行文件导出表的工具,以便查看实际导出的名称。