[速成] Visual Studio C/C++创建Dll(动态链接库)并调用

以下示例均在VS2022环境下完成。

一、创建动态链接库(C++)

1.新建动态链接库项目模版:

2.新建项目MyC++_Dll后,默认目录结构如下:

3.添加并新建头文件MyC++_Dll.h和源码文件MyC++_Dll.cpp(用于声明和定义函数接口):

4.MyC++_Dll.h示例如下:

#pragma once

#ifdef _EXPORTING
#define _DLL_API _declspec(dllexport)
#else
#define _DLL_API _declspec(dllimport)
#endif

#ifdef __cplusplus
class Dll_Class
{
public:
	Dll_Class();
	~Dll_Class();
	virtual int Addition(int a, int b);
};

extern "C"
{
	_DLL_API Dll_Class *CreateObject();
	_DLL_API void ReleaseObject(Dll_Class *pObject);
	_DLL_API int Multiplication_TypeC(int a, int b);
	_DLL_API int Addition_TypeC(int a, int b);
}
#endif

注意:

_EXPORTING 是笔者自定义宏,用于区分当前是导出dll还是调用dll,要实现导出函数,还需要在实现Dll函数功能的项目属性里,添加预处理定义(记得结尾加分号),如下图:

_declspec(dllexport) 是VC的关键字,表示导出函数到dll;

_declspec(dllimport) 是VC的关键字,表示从dll调用函数;

_DLL_API 是笔者自定义宏,用于给需要导入导出的函数接口简化代码、快速替换_declspec(dllimport)_declspec(dllexport)关键字;

如果_EXPORTING被定义,采用导出模式,否则为调用模式;

__cplusplus 宏表示采用的是C++的编译环境,通过#ifdef __cplusplus可判断当前是否为C++的编译环境;

extern "C" {} 表示代码块内的函数采用C语言方式编译.

5.MyC++_Dll.cpp示例如下(具体功能实现):

#include "pch.h"
#include "MyC++_Dll.h"

Dll_Class::Dll_Class() {

}

Dll_Class::~Dll_Class() {

}

int Dll_Class::Addition(int a, int b) {
	return a + b;
}

Dll_Class* CreateObject() {
	Dll_Class* pClass = new Dll_Class();
	return pClass;
}

void ReleaseObject(Dll_Class* pObject) {
	if (pObject) {
		delete pObject;
		pObject = NULL;
	}
}

int Multiplication_TypeC(int a, int b) {
	return a * b;
}

int Addition_TypeC(int a, int b) {
	return a + b;
}

6.编译代码生成lib和dll等文件,如下图:

二、创建动态链接库(C)

1.新建空项目MyC_Dll:

2.添加并新建头文件MyC_Dll.h和源码文件MyC_Dll.cpp(用于声明和定义函数接口):

3.MyC_Dll.h示例如下:

#ifndef _MYC_DLL_HEADER_FILE
#define _MYC_DLL_HEADER_FILE

#ifdef   _EXPORTING
#define  _DLL_API __declspec(dllexport)
#else
#define  _DLL_API __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C"
{
	_DLL_API int Addition_TypeC(int a, int b);
	_DLL_API int Multiplication_TypeC(int a, int b);
}
#endif
#endif

注意:

_EXPORTING 是笔者自定义宏,用于区分当前是导出dll还是调用dll,要实现导出函数,还需要在实现Dll函数功能的项目属性里,添加预处理定义(记得结尾加分号),如下图:

_declspec(dllexport) 是VC的关键字,表示导出函数到dll;

_declspec(dllimport) 是VC的关键字,表示从dll调用函数;

_DLL_API 是笔者自定义宏,用于给需要导入导出的函数接口简化代码、快速替换_declspec(dllimport)_declspec(dllexport)关键字;

如果_EXPORTING被定义,采用导出模式,否则为调用模式;

__cplusplus 宏表示采用的是C++的编译环境,通过#ifdef __cplusplus可判断当前是否为C++的编译环境;

extern "C" {} 表示代码块内的函数采用C语言方式编译.

4.MyC_Dll.cpp示例如下(具体功能实现):

#include "MyC_Dll.h"

int Addition_TypeC(int a, int b) {
	return a + b;
}

int Multiplication_TypeC(int a, int b) {
	return a * b;
}

5.要在项目属性里修改配置类型动态库(.dll)才能生成dll,如下图:

6.编译代码生成lib和dll等文件,如下图:

三、隐式调用Dll

1.创建空项目Call_dll:

2.添加并新建源码文件Call_Dll.cpp:

3.Call_Dll.cpp示例如下(具体调用函数接口实现):

//定义是否用C语言编译
//#define USING_C

#ifdef USING_C
#include <stdio.h>

#include "../MyC_Dll/MyC_Dll.h"
#pragma comment(lib, "../Debug/MyC_Dll.lib")
#else
#include <iostream>
using namespace std;

#include "../MyC++_Dll/MyC++_Dll.h"
#pragma comment(lib, "../Debug/MyC++_Dll.lib")
#endif

int main()
{
#ifdef USING_C
	int a = 8, b = 6;

	printf("Addition_TypeC result = %d\n", Addition_TypeC(a, b));
	printf("Multiplication_TypeC result = %d\n", Multiplication_TypeC(a, b));
#else
	int a = 8, b = 6;
	Dll_Class* pMyDll_Object = CreateObject();

	cout << "My_Dll_Class.Addition result = " << pMyDll_Object->Addition(a, b) << endl;
	cout << "Addition_TypeC result = " << Addition_TypeC(a, b) << endl;
	cout << "Multiplication_TypeC result = " << Multiplication_TypeC(a, b) << endl;

	ReleaseObject(pMyDll_Object);
#endif

	return 0;
}

注意:

(1)#pragma comment(lib, Lib文件)和 #include "dll头文件"要确保真实存在的路径.

(2)笔者这里用#ifdef USING_C来选择用C语言还是C++风格(二者主要区别在于用C还是C++编程语句,以及调用Dll的数据结构类型,是否是C++独有的)调用.

4.Dll文件复制到Call_Dll项目生成的目标路径,如下图:

注意:隐式调用,要求dll文件与exe文件在同一目录或者dll文件注册在操作系统的全局运行环境.

5.编译代码生成exe文件,运行结果如下图:

C++:

C:

四、显式调用Dll

1.创建空项目Call_dll:

2.添加并新建源码文件Call_Dll.cpp:

3.Call_Dll.cpp示例如下(具体调用函数接口实现):

//定义是否用C语言编译
//#define USING_C

#ifdef USING_C
#include <stdio.h>
#else
#include <iostream>
using namespace std;
#endif
#include <Windows.h>

int main()
{
	HINSTANCE hdll;

#ifdef USING_C
	typedef int (*_Fun_Addition_TypeC)(int, int);
	typedef int (*_Fun_Multiplication_TypeC)(int, int);

	hdll = LoadLibrary(L"MyC_Dll.dll");
	if (hdll == NULL) {
		printf("Error: Load dll fail.\n");
		return -1;
	}

	_Fun_Addition_TypeC Addition_TypeC;
	_Fun_Multiplication_TypeC Multiplication_TypeC;

	Addition_TypeC = (_Fun_Addition_TypeC)GetProcAddress(hdll, "Addition_TypeC");
	Multiplication_TypeC = (_Fun_Multiplication_TypeC)GetProcAddress(hdll, "Multiplication_TypeC");

	if (Addition_TypeC == NULL || Multiplication_TypeC == NULL) {
		printf("Error: Call functions fail.\n");
		return -2;
	}

	int a = 8, b = 6;
	printf("Addition_TypeC result = %d\n", Addition_TypeC(a, b));
	printf("Multiplication_TypeC result = %d\n", Multiplication_TypeC(a, b));
#else
	class _Dll_Class
	{
	public:
		//_Dll_Class();
		//~_Dll_Class();
		virtual int Addition(int a, int b)=0;
	};

	typedef _Dll_Class* (*_Fun_CreateObject)();
	typedef void (*_Fun_ReleaseObject)(_Dll_Class*);
	typedef int (*_Fun_Multiplication_TypeC)(int, int);
	typedef int (*_Fun_Addition_TypeC)(int, int);

	hdll = LoadLibrary(L"MyC++_Dll.dll");
	if (hdll == NULL) {
		printf("Error: Load dll fail.\n");
		return -1;
	}

	_Fun_CreateObject CreateObject = (_Fun_CreateObject)GetProcAddress(hdll, "CreateObject");
	_Fun_ReleaseObject ReleaseObject = (_Fun_ReleaseObject)GetProcAddress(hdll, "ReleaseObject");
	_Fun_Addition_TypeC Addition_TypeC = (_Fun_Addition_TypeC)GetProcAddress(hdll, "Addition_TypeC");
	_Fun_Multiplication_TypeC Multiplication_TypeC = (_Fun_Multiplication_TypeC)GetProcAddress(hdll, "Multiplication_TypeC");

	if (CreateObject == NULL || ReleaseObject ==NULL || Addition_TypeC == NULL || Multiplication_TypeC == NULL) {
		printf("Error: Call functions fail.\n");
		return -2;
	}

	int a = 8, b = 6;
	_Dll_Class* pMyDll_Object = CreateObject();

	cout << "My_Dll_Class.Addition result = " << pMyDll_Object->Addition(a, b) << endl;
	cout << "Addition_TypeC result = " << Addition_TypeC(a, b) << endl;
	cout << "Multiplication_TypeC result = " << Multiplication_TypeC(a, b) << endl;

	ReleaseObject(pMyDll_Object);
#endif

	if (hdll == NULL) {
		FreeLibrary(hdll);
		hdll = NULL;
	}

	return 0;
}

注意:

(1)LoadLibrary(dll文件路径)要确保真实存在的路径.

(2)笔者这里用#ifdef USING_C来选择用C语言还是C++风格(二者主要区别在于用C还是C++编程语句,以及调用Dll的数据结构类型,是否是C++独有的)调用.

 4.Dll文件复制LoadLibrary(dll文件路径)指定的路径,如下图:

注意:显式调用,要求dll文件路径LoadLibrary(dll文件路径)相同,当前示例与exe文件同目录。

5.编译代码生成exe文件,运行结果如下图:

C++:

C:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值