VS2019-静态库&动态库-多项目操作

4,036 阅读5分钟

前言:

一直好奇在VS编译器下,一个解决方案里如何进行多项目操作。

专门花时间研究了一下,也搜了很多博客关于使用静态库,但是几乎都是先写一个静态库文件,然后将需要的 .lib文件 和 .h文件 复制到需要调用的项目里。

虽然没啥问题,但是显得不方便,如果静态库要改,那每次都要复制,并且没有很好的利用VS多项目的功能。所以我这里整理一下使用VS2019进行静态库多项目的操作。


静态库

步骤:

创建一个名为 StaticLib 的空项目,或者直接建立静态库项目。因为直接选静态库项目会自动生成一些文件,暂时不需要。

如果选择的是空项目,需要更改项目属性,选择静态库。

现在就可以在 StaticLib 项目写代码。作为测试,我创建了一个lib类,代码如下:

//lib.h
#pragma once
class lib
{
public:
	int add(int a, int b);
};

//lib.cpp
#include "lib.h"
int lib::add(int a, int b)
{
	return a + b;
}

以上就将库文件写完了,下面再同一个解决方案下创建名为StaticLibCall的可执行文件,也就是一个空项目。

先不着急给StaticLibCall里写东西,先进行配置

结合静态库文件编译生成的 lib文件 需要复制到可执行项目里,我们直接设置 StaticLib 的输出目录,原本的输出位置默认是在改解决方案下创建一个Debug的文件夹,里面有两个文件,一个lib库文件,一个pdb文件(源代码调试用的)。

这里,我们更改输出目录,改到 StaticLibCall 目录下。

这样每次在编译库文件的时候,就不需要复制lib文件,但是.h头文件的问题没有解决。

其实头文件的问题很好解决,在使用的时候直接在#include 后写相对路径找到对应的.h文件即可。

此时,还需要给 StaticLibCall 设置依赖,保证每次编译先编译 StaticLib 再编译 StaticLibCall。

最后将 StaticLibCall 设置为启动项。就可以在StaticLibCall里调用静态库的函数了,例如,我创建了一个main.cpp,内容如下:

#include <iostream>
#include "../StaticLib/lib.h"
#pragma comment (lib,"StaticLib.lib")//指定与静态库一起连接

int main()
{
	lib b;
	std::cout << b.add(2, 3) << std::endl;
	return 0;
}

其中#pragma comment (lib,"StaticLib.lib")一定要有,不然会报错。

之后直接运行即可。


总结:

虽然上述让每次修改静态库库文件不需要再复制lib和h文件,但是暂时,我总觉得还有有点怪怪的,看博客还有其他人配置依赖项啥的,还没有弄得很清楚,之后还需要看看。

还有动态库的链接配置,我试验下再写。


补充:

经过学习,了解到另一种方法不用修改生成路径,直接进行链接。

具体的步骤类似上文,创建一个静态库文件,一个可执行文件,设置可执行文件的依赖。这里,不修改库文件的输出目录。

点开可执行文件的属性。设置链接器里常规里的附加库目录,就是整个解决方案里生成路径。

接着,设置链接器里输入里的附加依赖项。将库文件生成的lib文件的名字添加进去,注意分号。

设置完成之后就可以在可执行项目里使用,使用方式与上述相同。但是不用再写这句代码。

#pragma comment (lib,"StaticLib.lib")//指定与静态库一起连接

再补充: 第三种方法(最简单)

直接再可执行文件下的资源文件里,添加现有项,将lib文件直接添加,这样就可以直接使用,也不用修改配置。


动态库:

总体思路跟静态库没有区别,只是将项目设置为动态库dll。

主要使用的文件是动态库的 .dll .lib .h 三种文件

使用方法也与静态库类似,操作的依然是动态库的lib文件,不是dll文件。其实考虑之后静态库的三种方法,第一种并不推荐,因为直接更改了库的输出路径,显得很蠢,并且如果后期有很多的库,会不知道生成的文件在哪里。

值得注意的是,在写动态库的时候,头文件要加__declspec(dllexport),不然会报错。

//lib.h
#pragma once
class lib
{
public:
	__declspec(dllexport) int add(int a, int b);
};

补充:对于动态库在配置好环境之后,需要将dll文件放在输出文件夹(Debug/Release)里!!

解释一下:

DLL的函数分两种:

  1. DLL导出函数,可供调用dll的应用程序调用。
  2. DLL内部函数,只能在DLL程序使用,调用DLL的应用程序无法调用。

为什么动态库编译后不仅生成dll文件还生成了lib文件?

  • 动态库的 lib文件 与静态库的 lib文件 是不同的,动态库的 lib文件 只是dll文件里导出函数的声明和定位信息。没有函数的实现。而静态库的 lib文件 包含了函数的实现。因此静态库的 lib文件 只是作用在编译阶段,不需要对外发布。