首页 文章

mingw32 g和stdcall @suffix

提问于
浏览
1

我声明了一些C函数原型如下:

extern "C" void __stdcall function();

我也有一些导出 function() 的第三方dll - 根本没有名字装饰 . 由于MinGW的stdcall @ -suffix,因为 undefined reference to function@... ,我无法构建我的exe或dll . 如何在没有@的情况下获取目标文件...只是简单的函数名称?

2 回答

  • 6

    这听起来像是一种将这些外部函数导出到MinGW的 gnu ld 链接器可以使用的正确导入库的方法,但它涉及创建一个 .def 定义文件 . 这样做的好处是,一旦你创建了一个合适的导入库,就不必使用 --add-stdcall-alias--kill-at 之类的开关,因为导入库将包含编译器和链接器所需的符号 .

    以下是执行此操作的过程的大致轮廓:

    • 您需要一个工具调用 dlltool.exe ,它应该包含在与编译器相同的 MinGW/bin 目录中 .

    • 你'll need to create a definition file (*.def) listing all the external functions you'对进口感兴趣 .

    • 通过运行dlltool创建导入文件存根(* .a),传入您创建的.def文件作为输入 .

    • 在构建项目时将新创建的导入文件* .a传递给链接器,以便正确解析符号 .

    以下是定义文件的外观:

    ;Run the dlltool like this:
    ;dlltool -k -d third_party.def -l libthird_party.a
    LIBRARY third_party.dll
    
    EXPORTS
        dll_function1@0
        dll_function2@8
        dll_function3@16
    ;   ...
        dll_function_n@24
    

    几个重要的事情要注意 . EXPORTS 部分必须按照工具链的预期以相同的名称修饰格式列出导出的符号/函数 . 在这种情况下,MinGW编译器和ld链接器期望 __stdcall C函数附加'@'后跟参数中的字节数 . 需要注意的第二个重要事项是 dlltool -k 将删除'@',它与您已经看到的 --kill-at 选项的功能相同 . 最终结果是您有一个具有正确内部名称装饰的导入库,因此事情可以正确解析,并且内部名称将映射到第三方dll中找到的导出的可见名称 .

    最后一件事需要提及 . 在整个示例中,我们假设dll中未修饰的名称使用 __stdcall ,这不一定是真的 . 下面的图表(taken from here)显示了不同的编译器如何以不同的方式装饰 __cdecl__stdcall

    MSVC DLL
    Call Convention | (dllexport) | DMC DLL     | MinGW DLL  | BCC DLL
    ----------------------------------------------------------------------------
    __stdcall       | _Function@n | _Function@n | Function@n | Function
    __cdecl         | Function    | Function    | Function   | _Function
    

    您可以确保呼叫约定正确匹配,或者存在堆栈损坏和神秘程序崩溃的风险 .

  • 2

    man ld 为您提供 --enable-stdcall-fixup 选项,用于链接非@-装饰的库 . 我'm not sure if the leading underscores will be a problem, you'将不得不尝试 .

    如果你想用mingw生成目标文件或DLL,并希望导出名称没有"@", --kill-at 是你的朋友 .

相关问题