gcc -shared 是生成 dll 的核心命令,必须指定以告诉链接器创建动态链接库而非可执行文件;漏掉该选项会导致生成无效文件。

gcc -shared 是生成 DLL 的核心命令
Windows 下用 GCC(MinGW-w64)生成 DLL,gcc -shared 是唯一必须的选项。它告诉链接器不要生成可执行文件,而是打包成动态链接库。不加 -shared,哪怕源码里写了 __declspec(dllexport),最终产出仍是普通可执行文件或目标文件,不是 DLL。
常见错误现象:编译成功但生成的是 .exe 或无后缀文件,运行时报“不是有效的 Win32 应用程序”——本质就是漏了 -shared。
-
gcc -shared -o mylib.dll mylib.c是最简可行命令 - 如果源码含多个
.c文件,全部列在命令末尾:gcc -shared -o mylib.dll a.c b.c c.c - 不能用
-c单独编译再链接:DLL 必须一次性完成导出符号解析,分步会丢失__declspec(dllexport)语义
__declspec(dllexport) 不是可选修饰,而是导出函数的必要声明
Windows DLL 需显式声明哪些函数对外可见,__declspec(dllexport) 就是这个作用。GCC 默认不导出任何符号,即使函数名没被 mangled,没有这个修饰,GetProcAddress 或隐式链接都会失败。
容易踩的坑:只在头文件里声明函数,但在实现文件里忘了加 __declspec(dllexport);或者用了 C++ 编译但没包 extern "C",导致符号名被破坏。
- C 源码中直接写:
__declspec(dllexport) int add(int a, int b) { return a + b; } - C++ 源码中必须包裹:
extern "C" { __declspec(dllexport) int add(int, int); } - 宏定义更安全:
#define EXPORT __declspec(dllexport),然后用EXPORT int add(...)
生成 .lib 导入库要用 -Wl,--out-implib
如果你打算用隐式链接(即编译时直接链接 DLL 的符号),就需要一个 .lib 文件。GCC 自带的 ld 支持 -Wl,--out-implib 参数生成它,而不是靠第三方工具。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
注意:这个 .lib 是 MinGW 格式的(通常叫 libxxx.a),MSVC 项目无法直接使用。若需供 Visual Studio 调用,得额外转换或改用 CMake 设置 CMAKE_GNUtoMS。
- 生成 DLL 同时输出导入库:
gcc -shared -o mylib.dll mylib.c -Wl,--out-implib,libmylib.a - 链接时用该
.a文件:gcc main.c -L. -lmylib -o main.exe - 也可以跳过
.lib/.a,直接把mylib.dll当作链接对象:gcc main.c mylib.dll -o main.exe(仅限 MinGW 工具链)
资源文件(.rc)要先用 windres 编译成 .o 再参与链接
DLL 若需嵌入图标、版本信息或字符串表,就得处理 .rc 文件。GCC 不直接理解资源脚本,必须用配套的 windres 工具预处理。
关键点在于:windres 输出的是 COFF 格式目标文件,必须和 C 源码编译出的目标文件一起交给 gcc -shared,不能单独生成 DLL 再追加资源。
- 编译资源:
windres resource.rc -o resource.o - 链接进 DLL:
gcc -shared -o mylib.dll mylib.c resource.o - 确保
resource.rc中的路径(如图标路径)是相对当前工作目录的,否则 windres 找不到文件会静默失败
真正麻烦的从来不是命令本身,而是符号可见性控制、资源路径绑定、以及跨工具链(MinGW vs MSVC)的导入库格式兼容性——这些地方一错,DLL 看似生成成功,实际调用时根本找不到函数。










