动态链接库(dll)与静态连接库(lib)

一、前言

  1. dll(dynamic)动态链接库,包含多个程序执行的代码和数据,程序运行时是需要使用dll;
  2. lib(static)静态链接库,包含dll中各函数的入口信息,在程序编译时用到;
  3. 动态连接库可以使设计者隐藏函数的具体实现,便噶增加代码的复用性;
  4. 动态链接库参与的程序中,lib文件和dll文件都要用到。

二、dll的生成

头文件中增加下面几行代码

#pragma once
#ifdef XXXX_EXPORTS                        //如果定义了XXXX_EXPORTS 变量
#define DLL_API __declspec(dllexport)      //那么定义DLL_API为__declspec(dllexport)的别名
#else                                      //若梅定义
#define DLL_API __declspec(dllimport)      //定义DLL_API字段为导入
#endif

__declspec(dllexport)为导出标志;若要将某个类导出:

class DLL_API 类名

若要将某个函数导出:

extern "C" 返回值类型 DLL_API 函数名(参数1,参数2,...)

extern "C"表示在其他类中已经定义了该代码里内容,这里只是声明,“C”表明按照C语言方式进行编译和链接,因为C++编译时会对函数名进行修饰,用于实现函数的重载,而C里面没有这个功能,多以需要用extern “C”在而文件头声明时加以区分,以便链接时进行正确的函数名查找;

三、dll和lib的引用

  1. 属性—>输入—>附加依赖项,出入需要的XXX.lib文件;
  2. 将lib文件放到目标工程目录下,确保该目录是在属性—>c++—>常规—>附加包含目录中,若没有,添加即可;
  3. 将dll文件放到Debug/release文件下;
  4. 在工程文件中太你家与lib名称相同的头文件,文件最上方添加:
class __declspec(dllimport) XXX.lib

   

若导入函数:

extern "C" __declspec(dllimport) void 函数名(参数列表);

导入动态连接库可以也可以如下写法:

#include "../DLL/DLL.h"   //通过相对路径或绝对路径添加头文件
#pragma comment (lib,"../DLL/DLL1.lib")  //添加库文件

四、实例

dllExample.h

#pragma once
#include <iostream>
#ifdef DLL_EXPORTS
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
 
class DLL_API ExportInterface
{
public:
	virtual void foo() = 0;
	virtual ~ExportInterface()
	{
		std::cout << "call ~ExportInterface"<< std::endl;
	}
};
 
extern "C" DLL_API ExportInterface* getInstance();
extern "C" DLL_API void releaseInstance(ExportInterface* pInstance);
 
#ifdef DLL_EXPORTS  //我们并不需要向外导出该类的定义,在外部代码编译时,也不需要包含此类的定义。
class ExportClass : public ExportInterface
{
private:
	std::string x; //由于外部代码对此不可见,此处的std::string是安全的。
public:
	void foo(); //函数体在dllExample.cpp中实现
	virtual ~ExportClass()
	{
		std::cout << "call ~ExportClass" << std::endl;
	}
};
#endif

dllExample.cpp:

#define DLL_EXPORTS
#include "dlltest.h"
#include <iostream>
 
extern "C" DLL_API ExportInterface* getInstance()
{
	ExportInterface* pInstance = new ExportClass();
	return pInstance;
}
 
extern "C" DLL_API void releaseInstance(ExportInterface* pInstance)
{
	pInstance->~ExportInterface();
}
 
void ExportClass::foo()
{
	std::cout << "call func foo" << std::endl;
	//do something...
	return;
}

调用

#include <iostream>
#include <windows.h>
#include "dlltest.h"
using namespace std;
// 动态加载DLL
// 函数指针,用于获取GetProcAddress返回的函数地址,并调用DLL中的函数
typedef ExportInterface* (*DllGetInstance)(void);
typedef void (*DllReleaseInstance)(ExportInterface*);
 
int main()
{
	DllGetInstance getInstance;
	DllReleaseInstance releaseInstance;
	ExportInterface* pTest;
	// 显式加载
	HINSTANCE hInstLibrary = LoadLibrary("./TestDll.dll");
 
	if (hInstLibrary == NULL)
	{
		FreeLibrary(hInstLibrary);
		cout << "cant load dll" << endl;
	}
	getInstance = (DllGetInstance)GetProcAddress(hInstLibrary, "getInstance");
	releaseInstance = (DllReleaseInstance)GetProcAddress(hInstLibrary, "releaseInstance");
	if (getInstance == NULL || releaseInstance == NULL)
	{
		FreeLibrary(hInstLibrary);
		cout << "cant get func" << endl;
	}
	
	pTest = getInstance();
	pTest->foo();
	releaseInstance(pTest);
 
	std::cin.get();
 
	FreeLibrary(hInstLibrary);
 
	std::cin.get();
	return 0;
}

具体参考:

https://blog.csdn.net/fantasysolo/article/details/88553742?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-2

https://blog.csdn.net/AnthonyStark/article/details/98237701

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章