MinGW 使用和创建 DLL 应注意的问题


MinGW 是 GCC 的 Windows 版本,稳定版已经到了 4.5.2,功能和性能上很好,感觉不比 Microsoft 自家的 VC 差啊。但是 MinGW 下使用和创建 DLL 倒是要特别注意,问题主要集中在 g++ 编译器(C++ 的 GNU 版本编译器)对于 DLL 的函数输入以及输出的名称修饰、调用协议上和 VC 编译器是有很大区别的。

1、MinGW 如何使用一个标准的 DLL。这里标准 DLL 指的是采用 __stdcall 调用协议、并且导出函数名称干干净净,没有函数名尾部的 @nn、没有函数名头部的下划线的。MinGW 的 g++ 程序中,对于需要从 DLL 中导入的函数,声明时必须要用 extern "C",但不要用 __declspec(dllimport),虽然 g++ 支持,但是一旦你使用,则 g++ 在链接时会自动强制在需要导入的函数名前加 _imp__ 前缀,导致链接时找不到函数名错误。所以,我们其实完全不需要用 __declspec(dllimport)。另一方面,gcc/g++ 编译器遇到代码中 __stdcall 修饰的函数名,会自动将其函数名在链接时设置为函数名@nn,nn 是函数参数栈字节数。另外,gcc/g++ 编译器/链接器在链接时其实不需要 DLL 的导入库(import lib),因为它们可以直接从 DLL 链接,这样更加方便,省去了很多从 DLL 如何生成符合格式要求的 .a 导入库等问题。只需要在 gcc/g++ 参数中加入 -Wl,--enable-stdcall-fixup -L../../Bin/ -lDLL文件名(不含.dll)即可直接从 DLL 文件本身完成链接。这里要注意,-Wl参数指示 g++ 链接器需要采用后面的链接控制参数(以逗号分隔),--enable-stdcall-fixup 告诉 g++ 链接器需要导入的 DLL 函数的名字需要自动在尾部加上 @nn 格式的后缀,以便符合 gcc/g++ 对 __stdcall 函数名的扩展规范。-L 指定 DLL 文件所在目录,-l 指定 DLL 文件名称,不带 .dll。如果不加 --enable-stdcall-fixup,gcc/g++ 总是会报链接错误,因为 gcc/g++ 将代码中需要从 DLL 导入的函数名后面都强制加了 @nn,但是 DLL 中的函数名不带 @nn,没有 --enable-stdcall-fixup,很有可能就会出错。即时不出错,也会有很多警告,很有可能会导致程序 crash!注,在 NetBeans CDT 中,-Wl,--enable-stdcall-fixup -L -l 这样的参数在链接器参数设置中指定。

2、MinGW 如何创建一个标准的 DLL。MinGW 中创建标准 DLL,应该使用 __declspec(dllexport),包括 extern "C" 等都是和 VC 一样的。但要注意,这样编译链接生成的 DLL,导出的函数名尾部都带有 @nn,为了要去除它们,必须在链接器参数设置中使用 -Wl,--kill-at,它告诉链接器创建 DLL 时导出的函数名尾部不要带有 @nn。注,在 NetBeans CDT 中,上面这个参数同样是在链接器参数设置中指定。

综上,如果创建一个 DLL,同时这个 DLL 又需要导入其他 DLL 的函数,参数就可以统一为 -Wl,--kill-at,--enable-stdcall-fixup -L -l 这样了,很方便。感觉 MinGW 确实相当强悍,跨平台,可调性很灵活,性能也很强劲,更难能可贵的是,它是一个免费而又强大的编译器!当然,搭配 NetBeans CDT 更是相当好的一款 C/C++ 开发利器。

MinGW 创建的程序或 DLL 脱离 libgcc-xx-xx.dll 和 libstdc++-x.dll 运行库的方法

MinGW 沿袭了 Linux 下 gcc/g++ 的习惯,编译出的程序或者动态链接库(共享库)总是默认采用动态链接方式,需要系统中附带运行时库文件 libgcc-xx-xx.dll 和 libstdc++-xx.dll。那么如果我们不想发布程序时还要附带这两个运行库,该如何操作呢?通过参考 gcc/g++ 用户手册,发现只需要在编译器或链接器参数设置中使用 -static-libgcc 和 -static-libstdc++ 即可实现对这两个运行库的静态库链接,不必附带运行库了。如果采用参数 -static,那么表示所有涉及到的外部共享库都采用静态链接方式了。不过 MinGW 始终还是要依赖 msvcrt.dll 这个在 Windows 平台上的基本运行库,但相信任何 Windows 平台都不会少了 msvcrt.dll 这个文件的,这是 Windows 必然自带的系统文件啦。

本文永久更新链接地址

相关内容