如何用CMake搭配MinGW直接链接DLL文件?附项目配置方案
Windows下C++使用DLL库的说明及CMake配置
核心问题解答
在Windows系统中,C++代码不能直接链接DLL文件。DLL是运行时加载的二进制文件,编译器的链接阶段需要依赖对应的**导入库(.lib文件)**来获取DLL中导出符号(函数、类、变量等)的信息,才能生成可执行文件。网上提到的"无法直接链接DLL"或"需转为LIB文件",本质就是指必须通过导入库完成编译链接阶段的符号关联。
如果只有DLL文件而没有对应的.lib导入库,只能通过动态加载API手动加载DLL并调用其中的函数,这种方式不需要链接.lib,但代码实现会更繁琐。
有导入库时的CMake配置(常规场景)
假设你的libs目录下实际存在与DLL同名的导入库(first.lib、second.lib,通常DLL发布时会配套提供),对应的CMakeLists.txt可以按以下方式编写,适配你给出的项目结构:
# 最低CMake版本要求 cmake_minimum_required(VERSION 3.15) # 项目名称 project(my_project) # 设置C++标准 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # 创建可执行目标 add_executable(my_target app/main.cpp) # 引入头文件目录(DLL的函数/类定义) target_include_directories(my_target PRIVATE include) # 指定导入库所在目录 target_link_directories(my_target PRIVATE libs) # 链接导入库(链接器会自动匹配同名的.lib文件) target_link_libraries(my_target PRIVATE first second) # 编译后自动复制DLL到可执行文件输出目录(运行时需要) add_custom_command(TARGET my_target POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${PROJECT_SOURCE_DIR}/libs/first.dll" "${PROJECT_SOURCE_DIR}/libs/second.dll" $<TARGET_FILE_DIR:my_target> )
配置说明
target_include_directories:让编译器找到include目录下的头文件,这些头文件包含DLL导出符号的声明。target_link_directories:告诉链接器去哪里找导入库文件。target_link_libraries:将可执行目标与导入库链接,链接器会自动寻找libs目录下的first.lib和second.lib。add_custom_command:编译完成后把DLL复制到exe所在目录,避免运行时因找不到DLL而报错。
无导入库时的动态加载方案
如果确实只有DLL文件,没有对应的.lib,可以通过Windows提供的LoadLibrary、GetProcAddress等API手动加载DLL并调用函数。示例代码如下(以first.dll为例):
#include <windows.h> #include <iostream> // 根据DLL导出函数的签名,定义对应的函数指针类型 typedef void (*FirstExportedFunc)(); int main() { // 加载DLL文件 HMODULE firstDll = LoadLibrary(L"first.dll"); if (!firstDll) { std::cerr << "加载first.dll失败,错误码:" << GetLastError() << std::endl; return 1; } // 获取导出函数的地址 FirstExportedFunc func = reinterpret_cast<FirstExportedFunc>(GetProcAddress(firstDll, "FirstExportedFunc")); if (!func) { std::cerr << "获取函数地址失败,错误码:" << GetLastError() << std::endl; FreeLibrary(firstDll); return 1; } // 调用DLL中的函数 func(); // 释放DLL FreeLibrary(firstDll); return 0; }
这种情况下,CMake只需编译可执行文件,无需链接库,同样可以用add_custom_command将DLL复制到输出目录。
内容的提问来源于stack exchange,提问作者Arun Kumar
相关产品推荐
相关产品推荐

