C/C++动态库和静态库+Cmake+Windows

问题由来

前段时间实习,遇到了一个很有意思的现象,使用cmake的link_libraries()在Windows下调用动态库(win下的动态库为dll)时,会出现如下错误:

fatal error LNK1107: 文件无效或损坏

由于之前一直是在Linux下开发程序,用此方法调用Linux的动态库(Linux下的动态库为so)时,从未出现过此问题,所以做了一下探究。

探究过程

由于不能使用cmake的link_libraries()链接动态库,所以换成target_link_libraries()+绝对路径的方法链接,但是仍然会报相同的错误。但在换成link_directories()+target_link_libraries()+动态库名称时,发现cmake会提示找不到(动态库名称).lib。这就很奇怪,明明链接的文件夹下就只有一个动态库,而且叫(动态库名称).dll,怎么cmake会需要(动态库名称).lib,难道Windows下的cmake只能链接静态库?

探究结果

这里要先介绍一下Windows和Linux的动态库和静态库的区别:
在这里插入图片描述
在Windows下的动态库分为动态库本身.dll文件和动态库导入文件.lib,其中dll文件不参与编译参与运行,lib导入文件参与编译不参与运行,所以Windows下的cmake在想要调用dll动态库时,要链接dll动态库的导入文件.lib,而不是dll本身。Windows下的静态库则只有.lib。Linux的动态库和静态库则只有.os和.a。而Windows下的动态库的lib导入文件,需要在代码中加入__declspec(dlliexport)才可以生成,如下所示:

__declspec(dllexport) void HelloWorld();

示例工程

github工程链接

工程介绍

内容

1、hwlib为helloworld打印测试库,可以生成动态库和静态库,让下面的demo测试工程调用。
2、demo为调用hwlib库的测试工程,会生成基于动态库的可执行程序和基于静态库的可执行程序。

编译

1、hwlib

cd hwlib
mkdir build && cd build
cmake ..
cmake --build .
cmake --install .

会在C:\Program Files\下生成hwlib库文件夹,将其移动到demo目录下(demo目录已经包含hwlib库此步骤也可以忽略)。

2、demo

cd demo
mkdir build && cd build
cmake ..
cmake --build .

运行

编译后,在demo/build/下有两个可执行程序,main_static和main_shared,其功能都是在终端打印HelloWorld字符串,但是main_static可以直接执行,main_shared则需要依赖hwlib.dll动态库,如运行main_shared出现找不到动态库的错误,则可以将hwlib.dll放在和main_shared同一个文件夹下。

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
CMake中,你可以使用add_library命令来设置生成动态库静态库。add_library命令用于创建一个新的库目标,并指定库的类型。 要生成动态库,可以将add_library命令的第一个参数设置为库的名称,然后将第二个参数设置为SHARED。例如: ```cmake add_library(mylib SHARED source1.cpp source2.cpp) ``` 上面的例子中,我们创建了一个名为mylib的动态库目标,并将源文件source1.cpp和source2.cpp添加到该目标中。生成的动态库文件将具有与平台相关的扩展名(如.so、.dll或.dylib)。 要生成静态库,可以将add_library命令的第一个参数设置为库的名称,然后将第二个参数设置为STATIC。例如: ```cmake add_library(mylib STATIC source1.cpp source2.cpp) ``` 上面的例子中,我们创建了一个名为mylib的静态库目标,并将源文件source1.cpp和source2.cpp添加到该目标中。生成的静态库文件将具有与平台相关的扩展名(如.a、.lib或.a)。 默认情况下,CMake将根据操作系统和构建配置(如Release或Debug)来决定使用动态库还是静态库。但你也可以使用set_target_properties命令来显式地指定目标生成的库类型。例如: ```cmake set_target_properties(mylib PROPERTIES LINKER_LANGUAGE CXX) ``` 上面的例子中,我们将目标mylib的链接器语言设置为C++,这将影响生成的库的类型。 总之,通过在add_library命令中使用SHARED或STATIC作为第二个参数,可以设置生成动态库静态库。你也可以使用set_target_properties命令来显式指定库的类型。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值