一、简介
(一)功能
前面一篇文章:
讲了C++静态调用DLL的方法,本片文章将会介绍C++动态调用DLL的方法。
(二)配置
编译器:VS2019 社区版
项目类型:C++空项目
字符集:使用多字节字符集
(项目上右击——>"属性"——>"高级"——>"字符集"——>"使用多字节字符集")
配置方面,除了以上部分,没有其他特意做更改的地方,系统自动分配。
二、具体
(一)创建C++ “空项目”
此处不再赘述。
(二)添加.cpp文件
项目上右击——>“添加” ——>"新建项"——>“C++文件” ——>给文件取个名字(比如我的是”main.cpp)——>"添加"。
添加一些基本的代码,main 函数作为程序的入口
#include <iostream>
using namespace std;
void main()
{
cout << "这里是程序的入口" << endl;
}
(三)加载DLL
项目上右击——>"添加"——>"新建项"——>"C++类"——>给类取个名字(比如我的是”LoadDll)——>在接下来弹窗上点击"确定"。
到此处,项目中的文件如下图所示。
接下来,就可以往里面写具体的内容了。
(1)准备工作
动态调用DLL,不同于静态调用,没有DLL导出接口的.h文件,无法知道DLL的导出接口以及接口的规范,所以要想动态调用DLL文件,一定知道DLL的接口规范。
一般情况下,接口规范的来源有两种:
a. 自己写的动态库,自己知道规范
b. 别人提供的动态库,需要其提供接口规范文档
另外,通过Dependency Walkers 工具,可以查看DLL文件的接口名,但是看不到函数相关的参数。
(PS:如果有别的方法知道接口规范,或者我有说的不对的地方,或者有什么想补充的,欢迎各位路过的友友们补充。)
本篇文章,仍然调用"SimpleMath.dll",因为这个DLL是我自己写的,所以我清楚有哪些接口函数,接口函数的规范我也清楚,如下:
int Add(int a,int b);
int Minus(int a,int b);
(2)编写类
知道了函数的接口规范了之后,就可以开始写具体的加载过程了。
LoadDll.h文件
//LoadDll.h
#pragma once
#include "atlstr.h"
typedef int(__cdecl* pAdd)(int, int);
typedef int(__cdecl* pMinus)(int, int);
class LoadDll
{
public:
LoadDll();
~LoadDll();
private:
HMODULE m_hDll;
CString m_strLastErr; //存放错误信息
public:
bool Load(CString DLLFileName);//加载DLL,DLLFileName:DLL文件的全路径,ex.D:\SimpleMath.dll
CString GetLastError(); //返回报错信息
pAdd _Add;
pMinus _Minus;
LoadDll.cpp文件
//LoadDll.cpp
#include "LoadDll.h"
LoadDll::LoadDll()
{
_Add = NULL;
_Minus = NULL;
m_hDll = NULL;
m_strLastErr = "";
}
LoadDll::~LoadDll()
{
if (m_hDll) { FreeLibrary(m_hDll); m_hDll = NULL; }
}
bool LoadDll::Load(CString DLLFileName)
{
if (m_hDll) { FreeLibrary(m_hDll); m_hDll = NULL; }
//加载动态库
m_hDll = LoadLibraryEx(DLLFileName, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
if (NULL == m_hDll)
{
m_strLastErr = "Load DLL Failed: " + DLLFileName;
return FALSE;
}
//加载函数接口
_Add = (pAdd)GetProcAddress(m_hDll, "Add");
if (_Add == NULL)
{
m_strLastErr = "Can not find[Add]";
goto EXIT;
}
_Minus = (pMinus)GetProcAddress(m_hDll, "Minus");
if (_Minus == NULL)
{
m_strLastErr = "Can not find[Minus]";
goto EXIT;
}
return TRUE;
EXIT:
if (m_hDll) { FreeLibrary(m_hDll); m_hDll = NULL; }
return FALSE;
}
CString LoadDll::GetLastError()
{
return m_strLastErr;
}
(四)调用DLL
main.cpp文件
//main.cpp
#include <iostream>
#include "LoadDll.h"
using namespace std;
LoadDll g_SimpleMaths;
void main()
{
//cout << "这里是程序的入口" << endl;
string DLLPath = "D:\\00File\\OWN\\Demo\\Test\\Debug\\SimpleMath.dll";
if (g_SimpleMaths.Load(DLLPath.c_str())) //加载DLL成功
{
cout << "1+2=" << g_SimpleMaths._Add(1,2) << endl;
cout << "8-6=" << g_SimpleMaths._Minus(8,6) << endl;
}
else
{
cout << g_SimpleMaths.GetLastError().GetBuffer();//多字节编码下:CString-->string
}
}