【问题标题】:How do I stop name-mangling of my DLL's exported function?如何停止对我的 DLL 导出函数进行名称修改?
【发布时间】:2010-11-30 19:54:02
【问题描述】:

我正在尝试创建一个导出名为“GetName”的函数的 DLL。我希望其他代码能够调用此函数而不必知道损坏的函数名称。

我的头文件是这样的:

#ifdef __cplusplus
#define EXPORT extern "C" __declspec (dllexport)
#else
#define EXPORT __declspec (dllexport)
#endif

EXPORT TCHAR * CALLBACK GetName();

我的代码如下所示:

#include <windows.h>
#include "PluginOne.h"

int WINAPI DllMain (HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
{
     return TRUE ;
}

EXPORT TCHAR * CALLBACK GetName()
{
    return TEXT("Test Name");
}

当我构建时,DLL 仍然导出名称为“_GetName@0”的函数。

我做错了什么?

【问题讨论】:

    标签: c++ c extern name-mangling


    【解决方案1】:

    小修正 - 为成功通过 clinet 解析名称

    extern "C"
    

    必须在出口方和进口方一样。

    extern "C" 会将 proc 的名称简化为:"_GetName"。

    此外,您还可以借助 .def 文件中的 EXPORTS 部分强制使用任何名称

    【讨论】:

    • 嘿酷,这正是我所需要的。现在如果我想反过来呢?我有 C 函数,完全可以成为 c++ 成员函数(vtable,调用约定全部完成),但编译器认为它的名称应该被破坏。
    • 是的,C 和 C++ 使用不同的名称修饰规则。要执行您所询问的操作,您需要创建将从 C++ 类成员调用 C 函数的包装器
    • .DEF 文件是禁用名称修改的唯一方法。 extern "C" 仍将使用名称修饰,只是不像 C++ 需要的那样冗长。
    【解决方案2】:

    这对于具有__stdcall 约定的 DLL 导出是正常的。 @N indicates the number of bytes that the function takes in its arguments -- 在你的情况下,为零。

    请注意,the MSDN page on Exporting from a DLL 在使用“函数定义中的关键字 __declspec(dllexport)”时明确表示“使用 __stdcall 调用约定”。

    【讨论】:

    • here 所述,克服__stdcall 的混乱的唯一方法是使用:#pragma comment(linker, "/EXPORT:SomeFunction=_SomeFunction@@@23mangledstuff#@@@@")
    • 你的第一个链接坏了,第二个指向下载
    【解决方案3】:

    正确答案如下:

    extern "C" int MyFunc(int param);
    

    int MyFunc(int param);
    

    是两个使用不同内部命名的声明,第一个是 C 风格,第二个是 C++ 风格。

    构建工具需要内部命名来确定函数接收哪些参数、返回什么类型等,因为 C++ 更复杂(oop、重载、虚函数等) - 它使用更复杂的命名。调用约定也会影响 c 和 c++ 命名。

    这两种命名方式在以相同方式使用 __declspec(dllexport) 时都会应用。

    如果您想省略导出例程的名称修改,请在您的项目中添加一个模块定义文件,输入它(在这种情况下您不需要 declspec dllexport):

    LIBRARY mylib
    EXPORTS
      MyFunc
    

    这将省略显式名称修饰(以下示例)。

    _MyFunc (c style, __cdecl)
    _MyFunc@4 (c style, __stdcall)
    ?MyFunc@@YAHH@Z (c++ style, __cdecl)
    ?MyFunc@@YGHH@Z (c++ style, __stdcall)
    

    【讨论】:

      【解决方案4】:

      您可以使用“-Wl,--kill-at”链接器开关来禁用名称修改。

      例如,在 Code::Blocks 中,在自定义链接器设置中,添加: -Wl,--kill-at

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-03-19
        • 2021-09-12
        • 1970-01-01
        • 2016-08-05
        • 1970-01-01
        • 2011-08-23
        • 2011-01-31
        相关资源
        最近更新 更多