动态库和静态库的区别:静态库在程序的链接阶段被复制到了程序中,和程序运行的时候没有关系;动态库在链接阶段没有被复制到程序中,而是程序在运行时由系统动态加载到内存中供程序调用。使用动态库的优点是系统只需载入一次动态库,不同的程序可以得到内存中相同的动态库的副本,因此节省了很多内存。
正是由于动态库是在运行的时候加载到程序中,而不是像静态库在程序生成的时候就已经复制到了程序中,因此动态库需要配置环境变量,或者将dll复制到Windows system32中或者将dll放在exe执行文件的同一级目录下。对于静态库,调用函数的代码封装在lib中,函数的接口在头文件里;对于动态库dll,调用函数的代码封装在dll中,函数的接口文件在头文件里,但对于动态库,在生成的过程中,也会产生lib文件,动态库的lib文件是封装了函数的调用地址和其它的内存信息。
接下来讲讲生成动态库,打开vs,同样新建项目-动态库,在附加选项里改为空项目。接着对项目进行配置,动态库没有运行时选项,因为对于动态库的代码生成也必须为MT,在链接器里可以配置附加库目录和附加依赖项,这里的链接库依赖项自动为是,不用改。接着配置第三方库的头文件。
接下来配置完成后就可以编写动态库的方法了,具体代码编写的注意事项参考静态库的制作过程,对于在头文件中定义函数接口的地方需要在前面添加
_declspec(dllexport)输出动态库函数声明。
cpp文件中代码如下:
#include<iostream>
#include"lxdll.h"
using namespace std;
//函数的实现
char* getName(char* name)
{return name;
}
在h文件中代码如下:
#pragma once
//动态库导出函数的声明
_declspec(dllexport) char* getName(char* name);
然后生成,会在release目录下生成C++dll.dll和C++dll.lib两个文件,然后再加上头文件C++dll.h,有这三个文件就是一个完整的动态库。
接下就是使用动态库了,新建项目,C++代码生成选择MD,模式为release,首先先新建一个cpp文件,运行得到release目录,因为这里想采用导入动态库dll直接复制到EXE文件这个目录下。当然也可以配置环境变量或者放入system32中。将C++dll.dll复制到release目录下,将头文件C++dll.h和
C++dll.lib复制到程序目录里,然后引入头文件,引入lib目录,因为文件都复制过来了,因此不需要配置附加包含目录和附加库目录,只需要定义附加依赖项即可,附加依赖项为C++dll.lib。然后就可以直接调用头文件里的函数。
下面为调用的代码:
#include<iostream>
//dll库头文件
#include"lxdll.h"
using namespace std;
int main()
{//调用dll库函数char* myname = getName("huanhuncao");cout << myname << endl;system("pause");return 0;
}
下面为两个工程的文件:
https://download.csdn.net/download/qq_37781464/10861662
如果将C++的dll提供给其它语言调用,例如C#、python,那么就使用下面的方式。
头文件
#pragma once
/* 如果导出函数供C++调用 前面只需要加__declspec(dllexport) 因为C++允许函数重载,因此函数重名也可以 但其它语言例如C#、Python就不行 所以采用C语言的函数明明规则extern "C" __declspec(dllexport) 使用def文件前面这些都可以不要extern "C" __declspec(dllexport) 一般C++的默认调用方式__cdecl,需要调用方对函数清栈道 而其它语言无法请栈,因此对外提供api时还应该将接口声明为__stdcall,让api函数自己清栈 WINAPI就死__stdcall */
int __stdcall myadd(int a, int b);
源文件
#include"lxDll.h"
#include<iostream>
using namespace std;int __stdcall myadd(int a, int b)
{
return a + b;
}
def文件
;冒号用来def文件中注释一行
;导出函数
LIBRARY
EXPORTS
myadd @ 1
生成的dll用查看工具查看效果如下: