mingw32 g ++和stdcall @后缀 [英] mingw32 g++ and stdcall @suffix
问题描述
我声明了一些C ++函数的原型,如下所示:
I declared some C++ functions prototyped as follows:
extern "C" void __stdcall function();
我也有一些第三方的dll,并且导出了function()
-根本没有名称修饰.
由于MinGW的stdcall @ -suffix,由于undefined reference to function@...
,我无法构建我的exe或dll.我该如何在没有@ ...的情况下获取目标文件?只是普通的函数名?
I also have some third-party dll with exported function()
- no name decorations at all.
I'm unable to build my exe or dll due to undefined reference to function@...
, because of MinGW's stdcall @-suffix. How can I obtain object file without @... just plain function names?
推荐答案
听起来您正在尝试使用MinGW编译一个使用第三方dll中的外部C函数的程序.有一种方法可以将这些外部函数导出到MinGW的gnu ld
链接器可以使用的适当的导入库中,但这涉及到创建.def
定义文件.这样做的好处是,一旦创建了正确的导入库,您就不必费心使用--add-stdcall-alias
或--kill-at
之类的开关,因为导入库将包含编译器和链接器期望的符号.
It sounds like you're trying to use MinGW to compile a program that uses external C functions from a third-party dll. There's a way to export those external functions into a proper import library that MinGW's gnu ld
linker can use but it involves creating a .def
definition file. The advantage with this is once you create a proper import library you won't have to fiddle around with switches like --add-stdcall-alias
or --kill-at
because the import library will contain the symbols expected by the compiler and linker.
以下是执行此操作的大致过程:
Here's a rough outline of the procedure for doing this:
- 您需要一个工具调用
dlltool.exe
,该工具调用应包含在与编译器相同的MinGW/bin
目录中. - 您需要创建一个定义文件(* .def),其中列出了您要导入的所有外部函数.
- 通过运行dlltool传入创建的.def文件作为输入来创建导入文件存根(* .a).
- 在构建项目时将新创建的导入文件* .a传递给链接器,以便可以正确解析符号.
- You'll need a tool call
dlltool.exe
which should be included in the sameMinGW/bin
directory as the compiler. - You'll need to create a definition file (*.def) listing all the external functions you're interested in importing.
- Create the import file stub (*.a) by running dlltool passing in the .def file you created as input.
- Pass the newly created import file *.a to the linker when building your project so the symbols can be resolved properly.
定义文件的外观如下:
;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
选项相同.最终的结果是,您拥有一个具有正确内部名称修饰的导入库,因此事情可以正确解决,并且内部名称将映射到在您的3 rd中找到的导出的可见名称. 派对dll.
Couple of important things to note. The EXPORTS
section has to list the exported symbols/functions in the same name-decorated format as expected by the toolchain. In this case, MinGW compiler and ld linker expects __stdcall
C functions to be appended with an '@' follow by the number of bytes in the arguments. The second important thing to note is that dlltool -k
will remove the '@', which does the same thing as the --kill-at
option you've already seen. The end result of this is you have an import library with the correct internal name-decoration, so things resolve properly, and that internal name will map to the exported visible name found in your 3rd party dll.
最后一件事需要提及.在整个示例中,我们假定 dll中未修饰的名称使用了__stdcall
,但这不一定是正确的.下图(从此处获取)显示了不同的编译器如何用不同的方式修饰__cdecl
和__stdcall
:>
One final thing that needs mentioning. Throughout the entire example, we were assuming the undecorated names in the dll used the __stdcall
which isn't necessarily true. The following chart(taken from here) shows how different compilers decorate __cdecl
vs __stdcall
differently:
MSVC DLL
Call Convention | (dllexport) | DMC DLL | MinGW DLL | BCC DLL
----------------------------------------------------------------------------
__stdcall | _Function@n | _Function@n | Function@n | Function
__cdecl | Function | Function | Function | _Function
由您决定调用约定是否正确匹配,否则可能会导致堆栈损坏和神秘的程序崩溃.
It's up to you to make sure that the call conventions match-up properly or risk stack corruption and mysterious program crashes.
这篇关于mingw32 g ++和stdcall @后缀的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!