使用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
相关产品推荐
相关产品推荐

