1.静态库
静态库特点
· 运行不存在
· 静态库源码被连接到调用程序中
· 目标程序的归档
c语言静态库
- 创建一个静态库项目
- 添加库程序,源文件使用C文件
编译后产生lib文件:
C静态库的使用
库路径设置:可以使用pragma关键字设置
#pragma comment(lib,“…/lib/clib.lib”)
#pragma comment(lib,"../Debug/lib_Project.lib")
int main()
{
int sum, sub;
sum = clib_add(5, 3);
sub = clib_sub(5, 2);
printf("sum = %d,sub = %d\n", sum, sub);
return 0;
}
C++静态库
1)C++静态库的创建
2)添加库程序,源文件使用CPP文件
C++静态库的使用
库路径设置:可以使用pragma关键字设置
#pragma comment(lib,“…/lib/cpplib.lib”)
c++调用C的LIB时必须在函数申明前加上:extern "C"
动态库
1. 动态库特点
运行时独立存在
源码不会链接到执行文件
使用时加载
2. 与静态库的比较
由于静态库是将代码嵌入到使用程序中,多个程序使用时,会有多份代码,所以代码体积会增大。动态库的代码只需要存在一份,其他程序通过程序通过函数地址使用,所以代码体积小。
静态库发生变化后,新的代码需要重新链接嵌入到执行程序中。动态库发生变化后,如果库中函数的定义未变化,其他使用DLL的程序不需要重新链接。
3. 动态库的创建
· 创建动态库项目
· 添加库程序
· 库程序导出 - 提供给使用者库中的函数等信息
1)声明导出:使用_declspec(dllexport)导出函数(note:动态库编译链接后,也有LIB文件,是作为动态库函数映射使用,与静态库不完全相同)
2)模块定义文件.def
例如:
LIBRARY DLLFunc//库
EXPORTS//库导出表
DLL_mul//导出函数
_declspec(dllexport) int cppdll_add(int x, int y)
{
return x + y;
}
_declspec(dllexport) int cppdll_sub(int x, int y)
{
return x - y;
}
_declspec(dllexport) int cppdll_mul(int x, int y)
{
return x * y;
}
dll.lib文件中是dll文件名以及函数名和标号
2)动态库的调用
隐式链接:
显示链接:
#include<iostream>
#pragma comment(lib,"../Debug/DLL.lib")
using namespace std;
_declspec(dllimport) int cppdll_add(int x, int y);
_declspec(dllimport) int cppdll_sub(int x, int y);
_declspec(dllimport) int cppdll_mul(int x, int y);
int main()
{
int sum = cppdll_add(3, 5);
int sub = cppdll_sub(3, 5);
int mul = cppdll_mul(3, 5);
cout << "sum = " << sum << "sub = " << sub << "mul = " << mul;
return 0;
}
隐式转换,将dll放到六个目录中,建议放在执行文件同一目录下
显示链接:
#include<iostream>
#include <windows.h>
using namespace std;
typedef int(*ADD)(int m, int n);
typedef int(*SUB)(int m, int n);
typedef int(*MUL)(int m, int n);
int main()
{
HINSTANCE hDLL = LoadLibrary((LPCWSTR)L"DLL.dll");
cout << "hDLL : " << hDLL << endl;
ADD myAdd = (ADD)GetProcAddress(hDLL, "?cppdll_add@@YAHHH@Z");
cout << "myAdd : " << myAdd << endl;
int sum = myAdd(3, 5);
SUB mySUB = (SUB)GetProcAddress(hDLL, "?cppdll_sub@@YAHHH@Z");
cout << "mySUB : " << mySUB << endl;
int sub = mySUB(3, 5);
MUL myMUL = (MUL)GetProcAddress(hDLL, "?cppdll_mul@@YAHHH@Z");
cout << "myMUL : " << myMUL << endl;
int mul = myMUL(3, 5);
cout << "sum = " << sum << " sub = " << sub << " mul = " << mul;
FreeLibrary(hDLL);
return 0;
}
另一个导出方式:def
//在def中书写
LIBRARY
EXPORTS
cppdll_add @1
cppdll_sub @2
cppdll_mul @3
现在直接使用原函数名就能直接使用了
#include<iostream>
#include <windows.h>
using namespace std;
typedef int(*ADD)(int m, int n);
typedef int(*SUB)(int m, int n);
typedef int(*MUL)(int m, int n);
int main()
{
HINSTANCE hDLL = LoadLibrary((LPCWSTR)L"DLL.dll");
cout << "hDLL : " << hDLL << endl;
ADD myAdd = (ADD)GetProcAddress(hDLL, "cppdll_add");
cout << "myAdd : " << myAdd << endl;
int sum = myAdd(3, 5);
SUB mySUB = (SUB)GetProcAddress(hDLL, "cppdll_sub");
cout << "mySUB : " << mySUB << endl;
int sub = mySUB(3, 5);
MUL myMUL = (MUL)GetProcAddress(hDLL, "cppdll_mul");
cout << "myMUL : " << myMUL << endl;
int mul = myMUL(3, 5);
cout << "sum = " << sum << " sub = " << sub << " mul = " << mul;
FreeLibrary(hDLL);
return 0;
}
动态库中封装类
#define DLLCLASS_EXPORTS
#include "Dll_TEST.h"
int CMath::add(int x, int y)
{
return x + y;
}
int CMath::sub(int m, int n)
{
return m - n;
}
#pragma once
#ifdef DLLCLASS_EXPORTS
#define EXT_CLASS _declspec(dllexport)
#else
#define EXT_CLASS _declspec(dllimport)
#endif // DLLCLAS_EXPORTS
class EXT_CLASS CMath {
public:
int add(int x, int y);
int sub(int m, int n);
};
#include<iostream>
#include <windows.h>
#include "../DLL2/Dll_TEST.h"
#pragma comment(lib,"../Debug/Dll2.lib")
using namespace std;
int main()
{
CMath math;
cout << math.add(1, 2) << endl;
cout << math.sub(2, 1) << endl;
return 0;
}