Linux下使用MinGW编译32位Windows DLL时符号未找到问题求助
解决32位MinGW编译汇编DLL的符号导出与函数链接问题
你遇到的问题本质是32位和64位MinGW在符号处理、数学库实现上的差异导致的,下面分两部分拆解并给出修复方案:
1. 为什么mycode符号无法被导出?
在64位MinGW编译DLL时,链接器默认会自动导出全局符号,但32位MinGW的链接器不会这么做——它只会导出显式标记的符号。你需要明确告知链接器要导出mycode,有三种常用方法:
方法一:在汇编代码中添加导出标记
使用MinGW特有的汇编语法,在.global声明后添加.def块来标记符号为导出:
.global mycode .def mycode; .scl 2; .type 32; .endef # 标记mycode为导出函数 .text mycode: call _cos ret # 别忘了添加返回指令,否则函数执行后会崩溃
其中.scl 2表示符号外部可见,.type 32表示这是一个函数类型的符号。
方法二:用链接器参数强制导出所有全局符号
编译时添加-Wl,--export-all-symbols参数,让链接器自动导出所有全局符号:
i686-w64-mingw32-gcc -fPIC -m32 -shared -masm=intel -o test32.dll test.s -Wl,--export-all-symbols
方法三:使用.def导出文件
创建一个名为test.def的文件,内容如下:
EXPORTS mycode # 指定要导出的符号
然后编译时带上这个文件:
i686-w64-mingw32-gcc -fPIC -m32 -shared -masm=intel -o test32.dll test.s test.def
2. 为什么链接了-lm还是找不到cos?
这是32位MinGW数学库的特性导致的:
- 32位Windows平台下,MinGW已经把数学库(libm)的函数整合到了标准C库(msvcrt)中,不需要单独链接
-lm参数。 - 更重要的是,32位C函数的符号名称会带有下划线前缀(遵循cdecl调用约定的命名规则),所以你需要调用
_cos而不是cos,否则链接器找不到对应的符号。
把汇编代码里的call cos改成call _cos,同时去掉编译命令中的-lm,就能解决这个问题。
完整可运行的示例
汇编代码(test.s)
.global mycode .def mycode; .scl 2; .type 32; .endef .text mycode: call _cos ret
编译命令
i686-w64-mingw32-gcc -fPIC -m32 -shared -masm=intel -o test32.dll test.s
最后补充:你的原始代码缺少ret指令,这会导致函数执行完cos后无法正确返回,运行时必然崩溃,一定要加上哦。
内容的提问来源于stack exchange,提问作者Florian Bach
相关产品推荐
相关产品推荐

