静态链接库(*.lib)
如果在程序中使用静态链接库,那么链接器在链接的过程中会将*.obj文件和*.lib文件组织成可执行exe文件,也就是将.lib中的代码链接到可执行文件中,因此生成的exe文件比较大。程序运行时会将其所需数据一次性全部加载到内存,其缺点也比较明显:加载时间比较长。程序在发行时不需要提供库文件。
动态链接库(*.dll)
动态链接库又分为两种加载方式:隐式加载和显式加载。
隐式加载是程序载入内存时加载所需的dll文件,且该dll随主进程始终占用内存。在编码时需要使用#pragma comment(lib,"myDll.lib")获得所需函数的入口。注意该.lib与静态链接库的.lib文件不同,静态链接库的.lib中包含了所需函数的代码,动态链接库的.lib仅指示函数在dll文件中的入口。
显式加载是在程序运行过程中加载,不需要该dll时则将其释放。在需要时使用LoadLibrary加载,不需要时使用FreeLibrary释放。如果在LoadLibrary时该dll已经在内存,则只需将其引用计数加1,如果其引用计数减为0则移出内存。
使用动态链接库的程序在发行时需要提供dll文件。
在编译时,如果使用隐式链接则需要提供.lib文件,生成可执行文件后则不再需要该.lib。如果使用显式链接,在编译时不需提供.lib文件。
下面给出一个动态链接库的小Demo
dll源码:
#include <Windows.h>
#include <stdio.h>
extern "C" {
_declspec(dllexport) int testAdd(int x, int y)
{
return x + y;
}
}
使用隐式链接的主函数:
#include"stdafx.h"
using namespace std;
#pragma comment(lib,"myDll.lib")
extern "C" {
_declspec(dllimport) int testAdd(int x, int y);
}
int main(int argc, TCHAR *argv[]) {
_tprintf(_T("sum is %d\n"), testAdd(2,5));
system("pause");
return 0;
}
使用显式链接的主函数:
#include"stdafx.h"
using namespace std;
int main(int argc, TCHAR *argv[]) {
HINSTANCE h = LoadLibrary(_T("myDLL"));
GetErrorMessage(GetLastError(), 0);
int(*pAdd)(int, int) = NULL;
pAdd = (int(__cdecl *)(int, int))(GetProcAddress(h, "testAdd"));
GetErrorMessage(GetLastError(), 0);
if (pAdd == NULL) {
FreeLibrary(h);
return 0;
}
int sum = pAdd(239, 23);
_tprintf(_T("sum is %d\n"), sum);
FreeLibrary(h);
system("pause");
return 0;
}