以下代码是如何工作的(从DLL加载动态类)

How does the following code works(Dynamic Class loading from DLL)?

本文关键字:加载 动态 DLL 代码 何工作 工作      更新时间:2023-10-16

我想编写类并将它们导出到DLL中,然后在C++应用程序中使用它们。我在网上搜索,经过几天的研究,我终于找到了解决方案。问题是我不能正确理解代码。我不想盲目使用代码。我想知道它到底在做什么。这是我的密码。这是主要的应用程序源main.cpp

#include <Windows.h>
#include <iostream>
#include <conio.h>
#include "ILogEngine.hpp"
using namespace std;
int main(int argc, char **argv)
{
    HINSTANCE handle = LoadLibrary("LogEngine.dll");
    if (handle == NULL)
    {
    MessageBoxA(NULL, "LogEngine.dll not found!!!", "Fatal Error!!!", MB_ICONERROR);
    exit(1);
    }
    ILogEngine* (*create)();
    void (*destroy)(ILogEngine*);
    create = (ILogEngine* (*)())GetProcAddress(handle, "create_object");
    destroy = (void (*)(ILogEngine*))GetProcAddress(handle, "destroy_object");
    ILogEngine* logEngine = (ILogEngine*)create();
    logEngine->msg();
    destroy(logEngine);
_getch();
    return 0;
}

这是ILogEngine.hpp

#ifndef __ILOGENGINE_HPP
#define __ILOGENGINE_HPP
class ILogEngine
{
public:
ILogEngine();
virtual void msg();
virtual int genLog(char *);
};
#endif

这是LogEngine.cpp类的实现。

#include "ILogEngine.hpp"
#include <iostream>
using namespace std;
#define DLL_EXPORT __declspec(dllexport)
extern "C" DLL_EXPORT ILogEngine* create_object()
{
    return new ILogEngine;
}
extern "C" DLL_EXPORT void destroy_object( ILogEngine* object)
{
    delete object;
}
ILogEngine::ILogEngine()
{
}
void ILogEngine::msg()
{
    cout << "This is a message from DLL..." << endl;
}

我能理解其中的一些部分,但不能理解整个过程。有人能介绍一下这里发生了什么吗?具体地说,(ILogEngine* (*)())GetProcAddress之前的部分是什么,最好还有代码的其余部分。我知道这可能是一个很大的问题,但这确实会帮助我更好地理解这一点,因为我不知道这里发生了什么。

(ILogEngine* (*)())是一个强制转换,它被强制转换为类型"不带参数的函数指针,并返回一个指向ILogEngine的指针"。

就像ILogEngine* (*create)();是一个声明一样,它声明了一个变量create,该变量的类型是(你猜对了)指向函数的指针,不带参数,并返回一个指向ILogEngine的指针。

ILogEngine* (*create)();

这是指向不带参数并返回ILogEngine* 的函数的指针的声明

create = (ILogEngine* (*)())GetProcAddress(handle, "create_object");

GetProcAddress返回具有给定名称的函数的地址。(ILogEngine*)将返回的地址(即void*)强制转换为指定的类型。

在这之后,您在本地create指针中有create_object函数的地址(需要检查NULL-可能函数在给定的dll中不存在?),所以您可以调用它。

动态加载的工作原理如下:

  • LoadLibrary:加载DLL。返回的句柄被用了好几件事
  • GetProcAddress-将导出的DLL函数映射到函数指针。您将看到此函数调用以及强制转换为函数指针类型

注意C++名称很难使用,因此映射的DLL导出通常具有C名称。在本例中,create_object函数是用extern "C"声明的。

create_object,工厂函数创建一个C++对象,并返回类本身或已知基类(更常见)。