以下示例均在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:
版权归原作者 Felix Peng 所有, 如有侵权,请联系我们删除。