浅谈Windows平台下C++调用静态链接库的方式

1. 什么是静态链接库?为什么要用静态链接库?

维基百科上关于静态库的解释是这样的:在计算机科学里,静态库(英语:Static library, Statically-linked library),或称静态库,是一个外部函数与变量的集合体。静态库的文件内容,通常包含一堆程序员自定的变量与函数,其内容不像动态链接库那么复杂,在编译期间由编译器与连接器将它集成至应用程序内,并制作成目标文件以及可以独立运作的可执行文件。

由上面的解释可以很清楚的看到,静态库这个概念包含两个部分。一个是“库”,所谓库,其实就是一些程序员自定义的函数或者变量(对于C++来说可能还有自定义的类),这些函数或者变量能完成某些特定功能,因此被集合在一起成为库,以达到代码复用的目的。当然你可能会问,为什么要把这些函数或变量以库的形式给出呢?直接给源代码不是更好吗?的确,如果有源代码,我们直接把相应的.cpp或者.h文件添加到工程中就可以了,并不需要使用静态链接库。然而,很多情况下我们是得不到源代码的(源代码可能是商业机密),或者这些代码的提供者不愿让我们修改里面的代码,这时候使用库就是一个最好的选择;概念的第二部分是“静态”,所谓静态,是和动态相对应的。所谓静态,是指在编译期间由编译器与连接器将它集成至应用程序内,简单来讲,就是这部分代码已经在可执行文件里面了(Windows系统下是.exe文件),直接双击就能运行,不再需要其它的文件了。动态链接库则不同,动态链接库相关的代码并没有被集成到应用程序内,在Windows系统里动态链接库为.dll文件,如果只有.exe文件而缺少.dll文件,应用程序会提示找不到dll,不能正确运行。

由上面的说明可以得出静态链接库的优缺点:

  • 优点:发布时只发布.exe文件即可,库代码已经被整合到了可执行文件中,不必考虑客户计算机上有没有安装相应的库;
  • 缺点:可执行文件体积较大,若多个可执行文件引用同一个库,必须将库整合进每一个可执行文件中,不利于复用。

2. 如何编写静态链接库?(以Windows平台下Visual Studio为例)

我们以Windows平台下的Visual Studio为例,使用C++语言编写一个静态链接库,然后在另一个工程中进行调用。

2.1使用Visual Studio编写静态链接库

首先打开VS,新建项目,项目类型选择为“Visual C++ 控制台应用程序”。

静态调用链解析 java_静态链接库

然后在向导的应用类型处选择Static library,即静态链接库,点击Finish即可。

静态调用链解析 java_Test_02


点击FInish以后工程就建立好了,然后要向工程中添加一个源文件和一个头文件,源文件命名为Test.cpp,头文件命名为Test.h。其中Test.cpp中为函数的实现,Test.h中为函数的声明。

我们在Test.h中写一个示例函数的声明,这个函数接收一个int型变量,并把这个 变量的值作为返回值返回。

在Test.h添加以下代码:

//这是一段示例代码
#pragma once
extern int ReturnAInt(int val);

这段代码声明了一个函数,这个函数接收一个int型变量,返回一个int值。与一般函数声明不同的是,这个声明前面多了一个extern关键字,extern关键字说明这是一个外部函数,这个函数不由自己实现,而是外部的库实现的,以便链接器进行链接。

然后在Test.cpp中添加函数的实现代码:

#include "stdafx.h"
int ReturnAInt(int val)
{
    return val;
}

Build一下这个工程,就能在工程的目录里看到相应的.lib文件了,这就是生成的静态链接库文件。

2.2 在工程中引用静态链接库

下面我们新建一个工程,来引用上面编写好的静态链接库。

工程新建好后,把刚才编写的Test.h头文件拷贝到工程目录下。

静态调用链解析 java_c语言_03

在工程中添加头文件,选择添加已有头文件,把Test.h这个文件加入到工程中来,然后在工程中添加源文件Main.cpp,加入以下代码:

#include "Test.h"
#include <iostream>
int main()
{
    std::cout << ReturnAInt(15) << std::endl;
    getchar();
}

运行代码,我们会发现VS提示以下错误:

静态调用链解析 java_c语言_04

这是一个链接错误,提示无法解析ReturnAInt这个外部符号,说明虽然我们提供了这个函数的声明,但是VS找不到这个函数的实现,原因是我们没有指定.lib文件的位置,VS自然找不到。解决这个错误的方法有两种:

方法一是在Main.cpp中加入以下代码:

#pragma comment (lib,"..//Debug//CppLib.lib")

这行代码指明了.lib文件的位置,其中双引号内的部分按需要替换成文件的实际路径,这样VS就能够根据这个路径找到指定的静态链接库,进而进行链接了。

方法二是在VS的项目设置中指定.lib文件的位置。右键单击项目,选择Properties(属性),然后选择左侧VC++ Directories选项卡,编辑右侧Library Directories选项,把.lib文件所在目录添加进来。

静态调用链解析 java_静态调用链解析 java_05

静态调用链解析 java_c语言_06

点击OK后,右击工程中的References,把刚才的.lib文件添加到引用中。

静态调用链解析 java_c语言_07

点击OK即可。

以上两种方法任选一种即可,然后运行工程,错误没了,程序成功运行。

静态调用链解析 java_静态调用链解析 java_08

至此大功告成^_^