创建静态库
然后直接创建一个.h文件一个.cpp文件实现静态库中功能
libTest.c
#pragma once
extern int num;
int Add(int a, int b);
libTest.cpp
#include "libTest.h"
int num = 100;
int Add(int a, int b)
{
return a + b;
}
然后直接运行就会在debug生成文件夹中有一个.lib文件
如何使用静态库?
将静态库中的.h文件一个生成的.lib文件拷贝到要使用的工程文件中
将静态库使用的.h文件添加到项目中
使用静态库
#include "stdafx.h"
#include <stdio.h>
#include "libTest.h" //静态库头文件
#pragma comment(lib,"静态库.lib") //包含静态库
int main()
{
printf("num=%d\n", num); //使用静态库中的全局变量
printf("Add(1,2)=%d\n",Add(1,2)); //使用静态库中函数
getchar();
return 0;
}
动态库
创建方法同创建静态,静态库改为DLL
编写动态库代码
DllTest.h
#pragma once
//在动态库中的全局变量是不能被使用的(无法解析的外部符号)
extern _declspec(dllexport) int num;
//使用动态库需要加上_declspec(dllexport) 只要保证在函数前面就可以
//函数钱还需要加上extern "C" 防止C++改变函数名的问题
extern "C" _declspec(dllexport) int Add(int a, int b);
//动态库中使用类注意事项:
//需要在类前面加上 _declspec(dllexport) 或者在成员函数名前加上_declspec(dllexport)
//这两种方式任选其一都ok,不然就是无法解析的外部符号
//☆☆☆☆☆最关键的☆☆☆☆☆
//使用动态库中的类只能通过隐式调用的方式(也就是#pragma comment(lib,"动态库.lib"))
//使用显示调用(LoadLibrary())的方式是不可以的,都是无法解析的外部符号,即使是通过函数返回类指针对象之后
//使用该指针调用类的成员函数同样是无法解析的外部符号
class A;
extern "C" _declspec(dllexport) A* CreateA();
class _declspec(dllexport)A //在类名前加 _declspec(dllexport)
{
public:
int Multi(int a, int b); //或者在成员函数前加 _declspec(dllexport)
};
DllTest.cpp
#include "stdafx.h"
#include "DllTest.h"
#include <iostream>
using std::nothrow;
int num = 100;
int Add(int a, int b)
{
return a + b;
}
A* CreateA()
{
A* pA = new(nothrow) A();
if (pA == NULL)
{
printf("实例化对象失败\n");
}
return pA;
}
int A::Multi(int a, int b)
{
return a*b;
}
使用动态库
新建win32项目—>控制台应用程序—>空项目
将生成的.dll文件、.lib文件以及使用的.h文件拷贝到使用的项目中,将头文件添加至工程,具体过程如下
1、添加工程的头文件目录:工程—属性—配置属性—c/c++—常规—附加包含目录:加上头文件存放目录。
2、添加文件引用的lib静态库路径:工程—属性—配置属性—链接器—常规—附加库目录:加上lib文件存放目录。
3、添加工程引用的dll动态库:把引用的dll放到工程的可执行文件所在的目录下。
隐式调用动态库
需要.dll动态库文件、.lib导入库文件
第一种方式:#pragma comment(lib,xxx.lib)
//隐示调用方式使用动态库
//就很简单了.在生成DLL的时候.会对应生成lib.我们直接使用这个lib即可.跟直接使用静态lib库一样.
//但是需要注意我们也需要DLL
//这个lib库只是辅助信息.并不跟上面你的静态库lib一样.上面的静态库lib里面是有实质性的代码的.
#include "stdafx.h"
#include "DllTest.h"
#pragma comment(lib,"动态库.lib")
#include <stdio.h>
int main()
{
//printf("num=%d\n",num); //不能使用动态库中的全局变量
printf("Add(1,2)=%d\n", Add(1, 2)); //使用动态库中的函数
A a; //使用动态库中的类
printf("%d\n", a.Multi(2, 3));
A* pA = CreateA(); //使用动态库函数中创建的类对象
printf("%d\n", pA->Multi(3, 4));
getchar();
return 0;
}
第二种方式
直接在VS IDE中添加依赖项
显式调用动态库(不能使用类)
只有.dll动态库文件就可以了
//显示方式调用使用动态库
#include "stdafx.h"
#include "DllTest.h"
#include <stdio.h>
#include <Windows.h>
typedef int(*pAddFun)(int, int);
typedef A* (*pCreateFun)();
int main()
{
//加载动态库
HMODULE hModule = LoadLibrary(L"动态库.dll");
//获取动态库中的函数指针
pAddFun pAdd = (pAddFun)GetProcAddress(hModule, "Add");
printf("Add(1,2)=%d\n", pAdd(1, 2)); //或者使用 (*pAdd)(1,2)也是一样的
//不能使用类,无法解析的外部符号
//pCreateFun pCreate = (pCreateFun)GetProcAddress(hModule, "CreateA");
//A* pA = pCreate();
//printf("a.Multi(2, 3)=%d\n", pA->Multi(2, 3));
getchar();
return 0;
}
静态库和动态库的区别
静态库在汇编的时候将代码和exe文件联系起来,所以会导致生成的exe文件增大,链接之后可以将.lib的静态库文件删除了
动态库只是在需要的时候进行调用动态库中的内容,不会导致exe文件增大,但是在工程目录中要一直保留使用的动态库文件
动态库一般会有对应的导入库(.lib文件),方便程序静态载入动态链接库,如何没有导入库的话,那么只能通过显示调用的方式使用动态库了,自己加载动态库LoadLibrary(),自己获取动态库中的函数地址GetProcAddress()
有了导入库,只需要链接导入库后,按照头文件中的函数声明调用就可以了
导入库和静态库的区别
静态库包含了实际执行代码 、符号表等
导入库只有符号表地址这些了,保证程序找到对应函数的一些基本地址信息,代码是在动态库中的
动态库优点
DLL有助于共享数据和资源,多个应用程序可同时访问内存中DLL副本的内容
利于升级
静态库优点
静态库代码装载速度快,不需要考虑用户计算机上静态库文件是否存在
其他
debug和release的工程和动态库混合使用不影响
x64应用程序不能调用x32库,反之也一样,不能混合使用
如果想要使用64位程序使用32位的库有以下解决方案: