【问题标题】:Determining symbol names of the DLL确定 DLL 的符号名称
【发布时间】:2013-10-09 04:04:44
【问题描述】:

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

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

所以我们有以下代码。

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

【问题讨论】:

  • 它是 __stdcall 调用约定的标准装饰。函数指针声明中的 CALLBACK 宏也指定了 __stdcall。一般来说,使用 LoadLibrary + GetProcAddress 肯定是您要避免的,它太容易出错了。只需让链接器处理它,链接导入库。

标签: c++ winapi dll


【解决方案1】:

如果您不使用 .DEF 文件,导出名称将根据其调用约定进行修饰,以支持导出重载函数。见Why can't I GetProcAddress a function I dllexport'ed?

[T]装饰方案因建筑而异,因调用约定而异。因此,例如,如果函数从 PPC DLL 导出,则必须执行 GetProcAddress(hinst, "..SomeFunction"),但如果从 80386 DLL 导出为 extern "C" __stdcall,则需要 GetProcAddress(hinst, "_SomeFunction@8"),但如果是 @987654326 @你需要GetProcAddress(hinst, "@SomeFunction@8")

此外,C++ 修饰因编译器供应商而异。如果使用 Microsoft C++ 编译器编译,C++ 导出函数可能需要 GetProcAddress(hinst, "?SomeFunction@@YGXHH@Z"),但如果使用 Borland C++ 编译器编译,则需要一些其他修饰字符串。

因此,如果您希望人们能够GetProcAddress 获取函数,并且您希望您的代码可移植到多个平台,或者如果您希望他们能够从 C/C++ 以外的语言使用您的 DLL 或使用不同于 Microsoft Visual Studio 的 C++ 编译器,则必须按未修饰的名称导出函数。

请参阅The history of calling conventions, part3 了解各种名称装饰方案的说明。在这种情况下,该函数使用__stdcall 调用约定,因此它通过前置下划线和附加@ 符号以及它所采用的参数的字节数来修饰。它需要一个字大小的参数,总共 4 个字节,所以它被修饰为_GetStringLength2@4

【讨论】:

    【解决方案2】:

    要回答您的实际问题,请使用编译器的 TDUMP 或类似工具,或任何其他可以显示可执行文件导出表的工具,以便查看实际导出的名称。

    【讨论】:

      猜你喜欢
      • 2011-02-27
      • 1970-01-01
      • 2020-12-27
      • 2012-02-29
      • 1970-01-01
      • 2019-07-21
      • 1970-01-01
      • 2010-10-08
      • 1970-01-01
      相关资源
      最近更新 更多