VS2019 动态库的创建以及使用

本文详细介绍了在Visual Studio 2019中如何创建动态链接库(DLL),包括普通函数和类的封装,并讲解了静态调用与动态调用DLL的方法,涉及__declspec(dllexport)和__declspec(dllimport)的使用,以及LoadLibrary和GetProcAddress函数在动态调用中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、说明

动态链接库(Dynamic Link Library 或者 Dynamic-link Library,缩写为 DLL),是微软公司在微软Windows操作系统中,实现共享函数库概念的一种方式。
VS2019 提供了三种创建动态库的模式,如下图所示:
在这里插入图片描述

二、编写动态库

2.1 创建动态库

选择“具有导出项的(DLL)动态链接库”,vs会帮我们自动创建与项目同名的.cpp文件和.h文件,并在.h文件中定义好相关导出符号;如果选择“动态链接库(DLL)”则不会创建上述文件。
在这里插入图片描述
直到出现下图为止:
在这里插入图片描述

2.2 普通动态库封装

新建一个动态库工程,将其命名为Dll1,创建一个cpp文件,一个.h文件
在这里插入图片描述
在这里插入图片描述
结构如下:
在这里插入图片描述

说明一下extern “C” __declspec(dllexport) int Add(int a, int b);这一句代码

  1. 其中extern "C"的作用是告诉编译器将被它修饰的代码按C语言的方式进行编译
  2. __declspec(dllexport),此修饰符告诉编译器和链接器被它修饰的函数或变量需要从DLL导出,以供其他应用程序使用;
  3. 与__declspec(dllexport)相对的还有一句代码是__declspec(dllimport),此修饰符的作用是告诉编译器和链接器被它修饰的函数或变量需要从DLL导入。

2.3 将类封装为动态库

新建一个动态库工程,将其命名为Dll2,创建一个ClassTest的类,程序结构如图所示
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、动态库调用

上述代码直接生成,即可得到.lib和.dll文件

3.1 动态库的静态调用

新建一个空工程,复制上述两个程序的.h文件,将其导入,程序结构如图所示:
在这里插入图片描述

修改两个文件的.h文件

  1. 将__declspec(dllexport)替换为__declspec(dllimport)
  2. 加入#pragma comment(lib,"…/Debug/Dll2.lib"),此代码用来静态导入

说明:
不替换为 __declspec(dllimport)也能正确编译代码,但使用 __declspec(dllimport) 使编译器可以生成更好的代码。编译器之所以能够生成更好的代码,是因为它可以确定函数是否存在于 DLL 中,这使得编译器可以生成跳过间接寻址级别的代码,而这些代码通常会出现在跨DLL 边界的函数调用中。但是,必须使用 __declspec(dllimport) 才能导入 DLL 中使用的变量。

在这里插入图片描述
在这里插入图片描述
新建main函数,测试普通函数动态库的调用:
在这里插入图片描述
测试普通函数和类封装成的动态库的调用:
在这里插入图片描述

3.2 普通动态库的动态调用

新建空工程,新建main.cpp加入以下代码,运行即可
在这里插入图片描述

3.3 类封装成动态库的动态调用

新建动态库,命名为Dll4
新建base类,将其写为虚类,此类作为导出类:
在这里插入图片描述
新建classTest3,此类继承base
在这里插入图片描述
classTest3.cpp文件中极爱如导出句柄的函数:
在这里插入图片描述
此时Dll4 的结构如图所示
在这里插入图片描述
新建空白工程,复制base.h,创建main.cpp,程序结构如图所示:
在这里插入图片描述
修改base.h
在这里插入图片描述
main.cpp

#include <iostream>
#include <windows.h>
#include "Base.h"


using namespace std;

void Func1() {
	typedef int(*lpFunc)(int a, int b);
	HMODULE hModule;
	hModule = LoadLibrary(L"Dll1.dll"); //调用DLL	

	lpFunc Add = NULL;

	Add = (lpFunc)GetProcAddress(hModule, "Add");

	cout << Add(3, 5) << endl;

}
void Func2() {
	typedef Base* (*pfGetInst)();
	HMODULE hMod = LoadLibrary(L"Dll4.DLL");
	if (hMod)
	{
		pfGetInst pfGetInstance = (pfGetInst)GetProcAddress(hMod, "GetInstance");
		if (pfGetInstance)
		{
			//通过基类指针指向派生类对象
			Base* pInst = pfGetInstance();
			if (NULL != pInst)
			{
				cout << pInst->Add(1, 2) << endl;
			}
			if (NULL != pInst)
			{
				//释放对象
				delete pInst;
			}
		}
	}
}
int main()
{
	Func1();
	Func2();
	cin.ignore();
	return 0;
}

运行效果如下图所示:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值