vs2019dll的生成与调用

本文详细介绍了如何在Windows平台上创建和调用DLL(动态链接库),包括工程创建、代码实现、头文件配置、环境设置以及隐式调用和显示调用的区别。

前言

DLL,即动态链接库,是一种在Windows操作系统中广泛使用的文件类型。在大型项目开发中,通过将编写的功能封装成DLL,可以方便地将这些模块集成到一个程序中,提高团队开发效率。最近一段时间工作上用到dll的生成与调用,在此做一个小结。


一、dll的生成

1.1 dll工程创建

步骤1:创建dll工程,选择动态链接库(DLL)
在这里插入图片描述
步骤2:配置项目,添加工程名和保存路径
在这里插入图片描述
步骤3:预处理器设置,右击工程属性、在配置属性的C/C++下的预处理器下添加FOUR_OPERATIONS_DLL。
在这里插入图片描述
步骤4:创建头文件和源文件,头文件用于放入声明,源文件用于放入代码实现。
在这里插入图片描述
在这里插入图片描述

1.2 dll代码创建

步骤5:头文件代码,放入封装的类和函数的声明。

#pragma once
#include <iostream>

#ifdef FOUR_OPERATIONS_DLL
#define FOUR_OPERATIONS_API __declspec(dllexport)
#else
#define FOUR_OPERATIONS_API __declspec(dllimport)
#endif

class FOUR_OPERATIONS_API CFourOperations
{
public:
	void SetNum1(int iNum1);
	void SetNum2(int iNum2);

	int GetNum1();
	int GetNum2();

	int Addition();
	int Subtraction();
	int Multiplication();
	int Division();

private:
	int m_iNum1;
	int m_iNum2;
};

extern"C"
{
	FOUR_OPERATIONS_API int Square(int iNum);

	// 导出函数,返回类的实例的指针
	FOUR_OPERATIONS_API CFourOperations* CreateClassInstance();

	// 导出函数,释放类的实例指针
	FOUR_OPERATIONS_API void DeleteClassInstance(CFourOperations* instance);
}

步骤7:源文件代码,放入封装的类和函数的实现。

#include "pch.h"
#include "FourOperationsDll.h"

void CFourOperations::SetNum1(int iNum1)
{
	m_iNum1 = iNum1;
}

void CFourOperations::SetNum2(int iNum2)
{
	m_iNum2 = iNum2;
}

int CFourOperations::GetNum1()
{
	return m_iNum1;
}

int CFourOperations::GetNum2()
{
	return m_iNum2;
}

int CFourOperations::Addition()
{
	return m_iNum1 + m_iNum2;
}

int CFourOperations::Subtraction()
{
	return m_iNum1 - m_iNum2;
}

int CFourOperations::Multiplication()
{
	return m_iNum1 * m_iNum2;
}

int CFourOperations::Division()
{
	if (0 == m_iNum2)
	{
		return 0;
	}
	else
	{
		return m_iNum1 / m_iNum2;
	}
}

extern"C"
{
	FOUR_OPERATIONS_API int Square(int iNum)
	{
		return iNum * iNum;
	}

	// 导出函数,返回类的实例的指针
	FOUR_OPERATIONS_API CFourOperations* CreateClassInstance()
	{
		return new CFourOperations();
	}

	// 导出函数,释放类的实例指针
	FOUR_OPERATIONS_API void DeleteClassInstance(CFourOperations* instance)
	{
		delete instance;
	}
}

步骤6:在项目处右击选择重新生成,生成dll文件。
在这里插入图片描述
步骤7:由文件夹下找到生成的dll文件。
在这里插入图片描述

二、dll的调用

接下来我们尝试调用上一章所创建的dll。

2.1 环境配置

步骤1:首先,创建一个新的工程。
在这里插入图片描述
步骤2:在工程文件夹下,分别创建dll和include文件夹,放入我们上一章所生成的dll文件和头文件。
在这里插入图片描述

步骤3:创建一个demo源文件。
在这里插入图片描述
步骤4:添加头文件和lib
在这里插入图片描述

#include "..\include\FourOperationsDll.h"
#pragma comment(lib, "../FourOperationsDll/FourOperationsDll.lib")

步骤5:配置dll文件路径,右击项目属性,在配置属性下选择调试,单击环境后取消从父级或项目默认设置继承,在环境对话框下配置dll文件路径path=%path%;…/FourOperationsDll。
在这里插入图片描述

2.2 隐式调用

隐式调用是指编译器在编译时会自动处理DLL的加载和卸载。这种方式下,需要将DLL对应的.LIB文件(包含函数入口位置信息)加入到应用程序的工程中。当程序运行时,操作系统会根据.LIB文件中的信息加载相应的DLL文件到内存中。这种方法比较简单,适合常规需求,但可能会导致DLL被多次加载到内存中。

	// 隐示调用在配置好环境后可以直接创建类
	CFourOperations* p = new CFourOperations();

	int iNum1 = 10;
	int iNum2 = 6;

	// 调用dll的类成员函数
	p->SetNum1(iNum1);
	p->SetNum2(iNum2);

	std::cout << "iNum1 = " << p->GetNum1() << std::endl;
	std::cout << "iNum2 = " << p->GetNum2() << std::endl;
	std::cout << "iNum1 + iNum2 = " << p->Addition() << std::endl;
	std::cout << "iNum1 - iNum2 = " << p->Subtraction() << std::endl;
	std::cout << "iNum1 * iNum2 = " << p->Multiplication() << std::endl;
	std::cout << "iNum1 / iNum2 = " << p->Division() << std::endl;

	// 调用dll的函数
	std::cout << "iNum1^2 = " << Square(iNum1) << std::endl;

	// 释放对象
	delete p;
	p = NULL;

2.3 显示调用

显示调用是指程序在运行时手动加载和卸载DLL。这种方式不需要.LIB文件,而是通过特定的API函数(如LoadLibrary和FreeLibrary)来控制DLL的加载和卸载。显示调用允许程序在需要时才加载DLL,不需要时可以卸载,从而节省资源。缺

	// 显示调用需要手动调用dll
	HMODULE hDll = LoadLibrary(L"FourOperationsDll.dll");
	if (hDll == NULL) 
	{
		std::cerr << "Failed to load FourOperationsDll.dll" << std::endl;
		return;
	}

	// 创建函数指针
	typedef CFourOperations* (*CreateClassInstanceFunc)();
	typedef void (*DeleteClassInstanceFunc)(CFourOperations*);
	typedef int(*SquareFunc)(int);

	// 获取函数地址
	CreateClassInstanceFunc createClassInstance = (CreateClassInstanceFunc)GetProcAddress(hDll, "CreateClassInstance");
	if (NULL == createClassInstance)
	{
		std::cerr << "Failed to get CreateClassInstance function" << std::endl;
		FreeLibrary(hDll);
		return;
	}

	DeleteClassInstanceFunc deleteClassInstance = (DeleteClassInstanceFunc)GetProcAddress(hDll, "DeleteClassInstance");
	if (NULL == deleteClassInstance)
	{
		std::cerr << "Failed to get DeleteClassInstance function" << std::endl;
		FreeLibrary(hDll);
		return;
	}

	SquareFunc square = (SquareFunc)GetProcAddress(hDll, "Square");
	if (NULL == square)
	{
		std::cerr << "Failed to get Square function" << std::endl;
		FreeLibrary(hDll);
		return;
	}

	// 创建对象
	CFourOperations* p = createClassInstance();

	int iNum1 = 11;
	int iNum2 = 5;

	// 调用dll的类成员函数
	p->SetNum1(iNum1);
	p->SetNum2(iNum2);

	std::cout << "iNum1 = " << p->GetNum1() << std::endl;
	std::cout << "iNum2 = " << p->GetNum2() << std::endl;
	std::cout << "iNum1 + iNum2 = " << p->Addition() << std::endl;
	std::cout << "iNum1 - iNum2 = " << p->Subtraction() << std::endl;
	std::cout << "iNum1 * iNum2 = " << p->Multiplication() << std::endl;
	std::cout << "iNum1 / iNum2 = " << p->Division() << std::endl;

	// 调用dll的函数
	std::cout << "iNum1^2 = " << square(iNum1) << std::endl;

	// 释放对象
	deleteClassInstance(p);

	// 释放dll
	FreeLibrary(hDll);

总结

以上就是今天要讲的内容,本文仅仅简单介绍了dll的创建和调用等基本操作。新人能力有限,如有不足之处欢迎大佬指点纠正。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值