c++的链接库库分为静态、动态链接库两种。使用静态库编译时为静态编译,静态编译将静态库中的代码编译进程序,生成的程序能够独立运行。而使用动态链接库在编译时为动态编译,动态编译不将动态库中的代码编译进程序,生成的程序在运行时需要动态库的支持。
windows下链接库的分类以及加载方式

测试环境vs2005,下面介绍如何使用静态/动态库进行编译
静态库的使用
静态库的使用需要静态库文件.lib和相关的一组头文件
静态库文件:
libaaa.lib
与库相关的头文件:
a.h
在使用静态库的模块中包含库的头文件,一般包含具有所需功能模块(函数、类等)声明的头文件
在需要的地方使用库中的功能
接下来要为vs指明使用相应的静态库进行编译
方法一:
点击项目,属性

链接器,常规,附加库目录里面,加上所用到的静态链接库所在的目录

同样在链接器,输入,附加依赖项里面加上所用到的库文件的名字

方法二:
在代码中加入下面一句话,告诉链接器使用的库路径就可以了
之后编译运行即可
动态库的使用
动态库的使用需要动态库文件.dll、伴随动态库的.lib文件以及相关的头文件
动态库文件:
libabc.dll
伴随动态库的生成的.lib文件:
libabc.lib
动态库头文件:
abc.h
#pragma once
#ifdef LIBABC_EXPORTS
#define LIBABC_API __declspec(dllexport)
#else
#define LIBABC_API __declspec(dllimport)
#endif
extern "C" LIBABC_API int multiply(int);
extern "C" class LIBABC_API cABC{
private:
char symbol;
public:
cABC(char symbol);
void print_l();
};
其中的
#ifdef LIBABC_EXPORTS
#define LIBABC_API __declspec(dllexport)
#else
#define LIBABC_API __declspec(dllimport)
#endif
在编译时,dll项目会自动定义
LIBABC_EXPORTS宏,因此LIBABC_API将替换成__declspec(dllexport)导出函数,而在使用时,就会替换成__declspec(dllimport)作为动态库导入函数使用,从而实现在编译和使用时只用到一个头文件。extern "C"将函数导出为c语言形式的修饰符
动态库的使用方法有两种,静态加载与动态加载
静态加载
使用vs生成动态库dll文件时,会伴随生成一个lib文件。这个lib文件不是真正的静态链接库,而是动态库的导出文件。在编译时像静态编译一样将其中代码编译进程序,里面不包含真正实现功能的代码,而是包含程序运行时动态库的名字以及函数入口,真正实现功能的还是动态链接库。因此程序运行时还是需要动态链接库的支持。
动态链接库的静态加载方式,编译时需要相关的头文件以及lib文件。
对于动态库的静态加载方式就类似静态库的使用的方法
在需要库功能的模块中包含库的相关头文件
在需要的地方使用库中的功能
同样的为vs指明编译时用到的lib文件,也是有两种方法,与静态库的编译一模一样
方法一:

链接器,常规,附加库目录里面,加上所用到的lib文件所在的目录

同样在链接器,输入,附加依赖项里面加上所用到的库文件的名字

方法二:
在代码中加入
之后点击编译就可以生成程序了
动态库静态加载方式的特点
程序一运行就载入动态库
对于lib文件,在生成时就已经在其中包含了对应的动态库文件名字,并且使用时被编译进程序。因此动态库文件名必须固定,一旦改变就会无法使用。
动态加载
对于动态加载,在编译时只需要库相关的头文件就可以了。不需要.lib文件
动态加载主要用到三个函数
LoadLibrary()、GetProcessAddress()和FreeLibrary()
LoadLibrary()用于加载dll文件。参数为dll文件名称,返回dll句柄
GetProcessAddress()用于从dll文件中获取需要的函数地址,返回对应的函数指针。参数1为LoadLibrary()返回的dll句柄,参数2为所需要的函数名
FreeLibrary()用于卸载dll文件,参数为dll句柄
对于GetProcessAddress()的使用方法。例如库中存在函数
而从库中使用此函数功能,就需要有如下代码,定义一个函数指针类型pFunction(名字自己起),但是返回值与参数要与库中所包含函数的一样
之后用函数指针类型pFunction定义一个函数指针pFun,使用GetProcessAddress()的返回值为其赋值,并且GetProcessAddress()的返回值需要进行pFunction类型转换。
之后使用pFun函数即可实现所需要的功能
例子:
main.cpp
#include"abc.h"
#include<windows.h>
#include<iostream>
typedef int (*pFunction)(int);
int main(){
HINSTANCE hDll;
hDll=LoadLibrary(L"libabc.dll");
if(hDll==NULL){
std::cout<<"load library error!"<<std::endl;
return -1;
}
pFunction pFun=(pFunction)GetProcAddress(hDll,"multiply");
if(pFun==NULL){
std::cout<<"get procaddress error!"<<GetLastError()<<std::endl;
return -2;
}
std::cout<<"6的阶乘是:"<<pFun(6)<<std::endl;
FreeLibrary(hDll);
system("pause");
return 0;
}
之后点击编译生成程序即可
动态库动态加载的特点:
程序动态加载与卸载动态库文件。
可以在程序中指定动态库名字,也就是dll文件的名字可以改变
使用
由动态编译生成的程序不能直接使用,运行时依赖dll文件。需要将相应的动态链接库文件放入system32或程序所在目录下,windows会在上面的目录搜索所需的dll文件。
如果没有相应的dll文件程序就会出现类似提示

提醒
对于链接库的使用,要确保库的debug和release版本,32/64位数与使用的程序一致,否则在链接阶段就会出现符号引用的错误
动态库的lib文件在编译时用于编译进程序的,而dll不参与编译,在程序运行时被使用。
静态加载动态库,lib文件指被编译进程序,指明程序所需要的动态库文件名与函数入口,与LoadLibrary()、GetProcessAddress()的函数功能相似。动态库一开始就被载入,在程序结束时才被卸载。而使用LoadLibrary()、GetProcessAddress()、FreeLibrary()函数可以操作对库文件的装载和卸载。
对于VS的附加库目录,相当于gcc的
-L选项,指明链接库的搜寻目录,而附加依赖项,相当于gcc的-l选项,指明链接时使用的链接库名字