C++学习记录006——调用DLL(动态)

一、简介

(一)功能

前面一篇文章:

C++学习记录005——调用DLL(静态)

讲了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
    }
}

(五)实现效果

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 动态链接库(Dynamic Link Library,简称“DLL”)是一种Windows操作系统下的共享库文件,它可以被多个应用程序共享调用,能够方便多个程序之间共享代码和数据。而动态调用DLL就是在程序运行时,动态地加载DLL文件并执行其中的函数,它不需要把DLL文件中的函数载入内存,减少了程序的占用空间。 动态调用DLL的过程一般包括以下几步: 1. 加载DLL:程序会使用LoadLibrary函数来加载指定的DLL文件,它返回一个可用于调用DLL函数的句柄。 2. 导入DLL函数:使用GetProcAddress函数,根据DLL函数名称获得函数地址,使其可被调用。 3. 调用DLL函数:将DLL函数地址转换为正确的函数类型,传入参数并调用DLL函数。 4. 卸载DLL:使用FreeLibrary函数卸载已加载的DLL文件,释放内存空间。 动态调用DLL可以使代码更具灵活性和可维护性,适用于需要动态扩展或修改功能的程序。同时,它也提高了程序的效率和整体性能,减少了对系统资源的占用。不过,动态调用DLL需要谨慎使用,因为错误的调用会导致程序崩溃或出现安全漏洞。要注意正确传递函数参数和释放内存空间,避免内存泄漏问题。 ### 回答2: 动态链接库(Dynamic Link Library,DLL)是在Windows系统中常用的一种辅助程序。动态调用DLL意味着在运行时加载DLL,并使用其中的函数。相比于静态调用(在编译时将DLL函数链接到代码中),动态调用具有更大的灵活性和可重用性。 动态链接库通常包括一组函数,这些函数可以通过导出表(Export Table)进行访问。为了使用DLL中的函数,首先需要使用LoadLibrary函数将DLL加载到进程的地址空间中。加载完成后,还需要使用GetProcAddress函数获取DLL中特定函数的地址。 一旦获得了DLL中函数的地址,就可以使用类似于函数指针的方式调用它们。通过使用GetProcAddress函数返回的地址指针,将函数的参数传递到DLL函数中进行处理。当调用完成后,使用FreeLibrary函数将DLL从进程的地址空间中卸载。 总的来说,使用动态调用DLL可以实现在程序运行时动态加载和链接DLL中的函数,从而提供更大的灵活性和可重用性。 ### 回答3: 动态调用DLL,是指在程序运行期间,通过代码调用动态链接库(DLL)中的函数或方法,实现特定功能的过程。相对于静态链接库,动态调用DLL具有更加灵活和高效的特点。 在Windows平台上,可以使用Win32 API中提供的LoadLibrary、GetProcAddress等函数实现动态调用DLL。LoadLibrary函数用于加载DLL文件,并返回一个句柄,可以通过这个句柄获取DLL中导出函数的地址。而GetProcAddress函数则可以根据函数名称获取函数地址,即导出函数表中的函数指针。 使用动态调用DLL,可以动态地载入需要的库,从而减少了程序的运行时内存开支,而且可以实现不同版本动态链接库的切换。此外,动态调用DLL还可以实现模块化编程,使程序的各个部分之间更加独立和可重用。 需要注意的是,在使用动态调用DLL时,一定要确保DLL文件的正确性和可靠性。因为DLL文件的损坏或恶意篡改可能会导致程序崩溃或者安全漏洞。因此,在使用动态链接库时,务必进行严格的文件验证和权限控制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值