You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MinGW G++构建的C++ DLL调用时崩溃问题求助

问题解决:MinGW DLL调用崩溃 + 编译参数错误

先给你揪出最直接的崩溃根源,再解决MinGW编译DLL的各种坑:

1. 致命错误:函数指针完全绑定反了!

看你的测试程序代码,这里明显搞反了函数指针和导出函数的对应关系:

// 错误绑定:把strlen2(返回uint16_t)绑定到无返回值的c_print类型
c_print func_prn = (c_print)GetProcAddress(h,"strlen2");
// 错误绑定:把printstring(无返回值)绑定到返回uint16_t的c_strlen类型
c_strlen func_strl = (c_strlen)GetProcAddress(h,"printstring");

这种类型不匹配会直接导致栈帧混乱,调用时必然触发非法内存访问。修正成以下代码:

c_print func_prn = (c_print)GetProcAddress(h,"printstring");
c_strlen func_strl = (c_strlen)GetProcAddress(h,"strlen2");

这一步就能解决大部分崩溃问题。

2. MinGW编译DLL的正确姿势,告别WinMain错误

你之前被迫加dummy WinMain,是因为编译命令没告诉G++要生成DLL,默认按EXE编译,所以会找WinMain入口。

正确编译命令

用-shared或-mdll选项明确编译DLL:

# 推荐写法:-shared生成DLL,同时生成导入库
g++ -shared -o gehtnichdll.dll -s src/dllmain.cpp -Wl,--out-implib=gehtnichdll.a

或者用-mdll(和-shared等价,专门针对DLL场景):

g++ -mdll -o gehtnichdll.dll -s src/dllmain.cpp

参数解释:

  • -shared/-mdll:告诉编译器生成动态链接库而非可执行程序,此时不需要WinMain,你可以把代码里的dummy WinMain删掉。
  • -Wl,--out-implib=gehtnichdll.a:生成对应的静态导入库,如果你后续想用静态链接方式调用DLL可以用,动态调用(LoadLibrary)的话可省略。
  • 移除--subsystem,windows:这个参数是给EXE指定运行子系统(控制台/窗口)的,DLL不需要设置。

解决LoadLibrary错误193

你之前用-mdll出现错误193,90%是架构不匹配:

  • 32位MinGW编译的DLL只能给32位MSVC程序调用,64位同理。
  • 检查MinGW位数:执行g++ -v,看输出里的target字段,i686-w64-mingw32是32位,x86_64-w64-mingw32是64位,要和你的MSVC测试程序编译架构一致。

3. 关于libstdc++初始化的补充

你的简化代码里已经移除了C++类,但如果后续要用到STL(比如std::string):

  • MinGW的DLL在DLL_PROCESS_ATTACH时会自动完成libstdc++的初始化,不需要额外操作。
  • 注意:不要跨编译器传递C++对象(比如把MinGW的std::string传给MSVC程序),两者STL实现完全不同,内存布局和命名都不兼容,必然崩溃。跨语言/编译器调用时,只使用基本类型、C风格字符串、POD结构体。

4. 修正后的测试效果

修正函数指针绑定和DLL编译命令后,测试程序的所有调用都会正常执行:

  • dummy_add(4,7)会返回11并正常打印。
  • strlen2("lenth of this string")会正确计算字符串长度。
  • printstring("hello world")会正常输出内容。
  • AA__create和AA__step也能正常执行,不会崩溃。

内容的提问来源于stack exchange,提问作者Blindleistung

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 06:09:11