网站的点击率,wordpress 中文在线字体,做h的小说网站有哪些,美图秀秀在线制作VS中动态库的创建和调用
库
库是写好的现有的#xff0c;成熟的#xff0c;可以复用的代码。库的存在形式本质上来说库是一种可执行代码的二进制。
库有两种#xff1a;静态库#xff08;.a、.lib#xff09;和动态库#xff08;.so、.dll#xff09;。所谓静态…VS中动态库的创建和调用
库
库是写好的现有的成熟的可以复用的代码。库的存在形式本质上来说库是一种可执行代码的二进制。
库有两种静态库.a、.lib和动态库.so、.dll。所谓静态、动态是指链接阶段静态库的链接阶段是在项目编译的时候静态链接。动态库是在程序运行的时候由代码加载链接。
静态库和动态库的区别主要是在链接阶段处理库的方式不同而区分的。
静态库
概念
静态库指的是在链接阶段直接将库和目标文件一起打包成可执行文件的方式所使用的库就称为静态库。
体现形式
.a 或者 .lib 文件
优缺点
优点 ①使可执行文件依赖项少已经被打包到可执行文件中了。 ②编译阶段完成链接执行期间代码装载速度快
缺点①使可执行文件变大。②若作为其他库的依赖库将会造成多余的副本因为必须与目标文件打包。③升级不方便升级必须重新编译
静态库的创建
使用VS创建一个空项目创建空项目之后将项目设置为静态库点击项目 - 属性 - 常规 - 配置类型中修改配置项目lib输出位置常规 - 输出目录 指的是dll输出的文件位置书写接口在静态库中只要是可以允许访问的函数和类都可以被使用没有特别的函数导入和导出。
例程
#pragma once
#include iostreamclass Arithmetic
{
public:// Returns a bstatic double Add(double a, double b);//可以调用// Returns a - bstatic double Subtract(double a, double b);//可以调用// Returns a * bstatic double Multiply(double a, double b);//可以调用// Returns a / bstatic double Divide(double a, double b);//可以调用void fun2();//可以调用private:static void fun();//不可以调用void fun1();//不可以调用
};
#include Arithmetic.hdouble Arithmetic::Add(double a, double b)
{return a b;
}double Arithmetic::Subtract(double a, double b)
{return a - b;
}double Arithmetic::Multiply(double a, double b)
{return a * b;
}double Arithmetic::Divide(double a, double b)
{return a / b;
}void Arithmetic::fun2() {std::cout 公共 void Arithmetic::fun2() std::endl;
}void Arithmetic::fun() {std::cout 私有 static void Arithmetic::fun() std::endl;
}
void Arithmetic::fun1() {std::cout 私有 void Arithmetic::fun1() std::endl;
}静态库的调用
创建一个项目配置项目属性导入静态库位置。导入头文件C/C - 常规 - 附加包含目录 指的是需要使用的自己编写的头文件导入库文件链接器 - 常规- 附加库目录 指的是在调用的时候声名需要使用的lib文件。添加导入lib名称链接器 - 输入 - 附加依赖项 指的是在调用的时候声名需要使用的lib文件。引入库的头文件之后直接使用库即可。
动态库
概念
动态库指的是在程序运行过程中动态加载库的方式使用的库也就是动态库的链接是发生在程序运行时期的它和可执行文件是分开的只是可执行文件在运行的某个时期调用了它。
体现形式
.DLL、.lib 和 .a 、.so ;
优缺点
好处程序自身的体积不会因为动态函数库变大。 缺点就是程序运行过程中使用到了这些函数库内的功能时万一系统特定的位置没有对应的动态库。就会造成程序崩溃或者各种奇怪的问题。
动态库的创建
在介绍动态库的创建之前我们先来了解以下的宏。
#pragma once
#ifdef PUBFUN_EXPORTS
#define PUBUTIL_DLL __declspec(dllexport)
#else
#define PUBUTIL_DLL __declspec(dllimport)
#endifMSVC编译器提供了一系列C/C的扩展来指定符号的导入导出即__declspec属性关键字。
dllexport与dllimport存储级属性是微软对C和C的扩展可用于从dll中导入或导出函数、数据、对象objects
__declspec(dllexport) 表示该符号是从本DLL导出的符号。
__declspec(dllimport) 表示该符号是从别的DLL中导入的。
我们在创建动态库的时候需要用到上面的宏。
创建方式1使用空项目
使用VS创建一个空项目创建空项目之后将项目设置为动态库点击项目 - 属性 - 常规 - 配置类型中修改配置项目lib 和 DLL 输出位置常规 - 输出目录 指的是dll输出的文件位置创建一个header.h 此文件名可以自由定义定义之后将上面的宏写入到文件中宏名称可以自己定义。使用定义的宏定义动态库导出的函数或者类。编译生成动态库。
例程
创建动态库导出导入宏
//header.h
#pragma once
#ifdef BD_TEST
#define BDTEXT_DLL __declspec(dllimport)
#else
#define BDTEST_DLL __declspec(dllexport)
#endif使用宏定义导出的函数
//testDLL.h
#pragma once
#include header.hint BDTEXT_DLL add(int a, int b);导出函数功能的实现
//testDLL.cpp
#include testDLL.hint add(int a, int b) {return a b;
}编译 这就是最后编译出来的lib和dll库。
创建方式2直接创建动态库项目
使用直接创建动态库项目会在项目中生成一个dllMain.cpp的文件。如下
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include pch.hBOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{switch (ul_reason_for_call){case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH:case DLL_THREAD_DETACH:case DLL_PROCESS_DETACH:break;}return TRUE;
}根据微软官网说明
DllMain是动态链接库 (DLL) 的可选入口点。 当系统启动或终止进程或线程时它将使用进程的第一个线程为每个加载的 DLL 调用入口点函数。 使用 LoadLibrary 和 FreeLibrary 函数加载或卸载 DLL 时系统还会调用 DLL 的入口点函数。
之后其他的接口函数和接口类和空项目的建立是一样的。
动态库的调用
创建一个项目导入头文件C/C - 常规 - 附加包含目录 指的是需要使用的自己编写的头文件导入库文件链接器 - 常规- 附加库目录 指的是在调用的时候声名需要使用的lib文件。添加导入lib名称链接器 - 输入 - 附加依赖项 指的是在调用的时候声名需要使用的lib文件。引入库的头文件之后直接使用库即可。将于lib配套的dll放到执行文件exe所在的文件目录下。
例程
配置头文件 配置lib文件位置 配置需要使用lib文件 配置完成之后编写代码
#include iostream
#include testDLL.h//引入头文件int main() {std::cout add(2, 5) std::endl; //调用库中的函数getchar();return 0;
}注意点 1、没有设置为导出的函数名称或者类无法在外部调用dll使用。导出的函数和类必须使用导出宏修饰。 项目常见配置项
常规 - 输出目录 指的是dll输出的文件位置
常规 - 中间目录 指的是中间件的输出位置
常规 - 配置类型 指的是项目类型
VC目录 - 包含文件 指的是三方库文件的头文件位置
VC目录 - 库目录 指的是三方库文件.dll .lib文件
C/C - 常规 - 附加包含目录 指的是需要使用的自己编写的头文件
C/C - 预处理器 - 预处理器定义 指的是我们需要配置的宏定义
链接器 - 输入 - 附加依赖项 指的是在调用的时候声名需要使用的lib文件。
链接器 - 高级 - 导入库 指的是lib导出的文件位置