gpt4 book ai didi

C++:从 dll 动态加载类

转载 作者:IT老高 更新时间:2023-10-28 21:38:58 39 4
gpt4 key购买 nike

对于我当前的项目,我希望能够从 dll 加载一些类(这并不总是相同的,甚至在我的应用程序编译时可能不存在)。给定的类也可能有多个替代 dll(例如 Direct3D9 的实现和 OpenGL 的一个实现),但任何时候都只会加载/使用其中一个 dll。

我有一组定义接口(interface)的基类以及我要加载的类的一些基本方法/成员(即用于引用计数的方法/成员),然后 dll 项目在创建类时从中派生。

//in namespace base
class Sprite : public RefCounted//void AddRef(), void Release() and unsigned refCnt
{
public:
virtual base::Texture *GetTexture()=0;
virtual unsigned GetWidth()=0;
virtual unsigned GetHeight()=0;
virtual float GetCentreX()=0;
virtual float GetCentreY()=0;
virtual void SetCentre(float x, float y)=0;

virtual void Draw(float x, float y)=0;
virtual void Draw(float x, float y, float angle)=0;
virtual void Draw(float x, float y, float scaleX, flota scaleY)=0;
virtual void Draw(float x, float y, float scaleX, flota scaleY, float angle)=0;
};

问题是我不知道如何做这一切,以便可执行文件和其他 dll 可以加载和使用这些类,因为我只使用过只有一个 dll 的 dll,我可以让 Visual Studio 链接器排序使用我在编译 dll 时得到的 .lib 文件。

我不介意使用工厂方法来实例化类,它们中的许多已经设计好了(即 Sprite 类是由主图形类创建的,例如 Graphics->CreateSpriteFromTexture(base::Texture*)

编辑:当我需要编写一些用于 python 的 c++ dll 时,我使用了一个名为 pyCxx 的库。生成的 dll 基本上只导出了一个方法,该方法创建了“模块”类的一个实例,然后可以包含工厂方法来创建其他类等。

生成的 dll 可以通过 "import [dllname]"导入到 python 中。

//dll compiled as cpputill.pyd
extern "C" void initcpputill()//only exported method
{
static CppUtill* cpputill = new CppUtill;
}

class CppUtill : public Py::ExtensionModule<CppUtill>
{
public:
CppUtill()
: Py::ExtensionModule<CppUtill>("cpputill")
{
ExampleClass::init_type();

add_varargs_method("ExampleClass",&CppUtill::ExampleClassFactory, "ExampleClass(), create instance of ExampleClass");
add_varargs_method("HelloWorld", &CppUtill::HelloWorld, "HelloWorld(), print Hello World to console");

initialize("C Plus Plus module");
}
...
class ExampleClass
...
static void init_type()
{
behaviors().name("ExampleClass");
behaviors().doc ("example class");
behaviors().supportGetattr();
add_varargs_method("Random", &ExampleClass::Random, "Random(), get float in range 0<=x<1");
}

这究竟是如何工作的,我可以在纯 c++ 环境中使用它来解决我的问题吗?

最佳答案

恕我直言,最简单的方法是使用一个简单的 C 函数,该函数返回指向别处描述的接口(interface)的指针。然后,您的应用可以调用该接口(interface)的所有功能,而无需实际知道它使用的是什么类。

编辑:这是一个简单的例子。

在您的主应用代码中,为界面创建一个 header :

class IModule
{
public:
virtual ~IModule(); // <= important!
virtual void doStuff() = 0;
};

主应用程序被编码为使用上面的接口(interface),没有关于接口(interface)的实际实现的任何细节。

class ActualModule: public IModule
{
/* implementation */
};

现在,模块 - DLL 具有该接口(interface)的实际实现,甚至不必导出这些类 - __declspec (dllexport) 不需要。模块的唯一要求是导出单个函数,该函数将创建并返回接口(interface)的实现:

__declspec (dllexport) IModule* CreateModule()
{
// call the constructor of the actual implementation
IModule * module = new ActualModule();
// return the created function
return module;
}

注意:错误检查被遗漏了——你通常想检查一下,如果 new 返回了正确的指针,你应该保护自己免受 ActualModule 类的构造函数中可能抛出的异常的影响.

然后,在您的主应用程序中,您只需加载模块(LoadLibrary 函数)并找到函数 CreateModule(GetProcAddr 功能)。然后,您通过接口(interface)使用该类。

编辑 2:您的 RefCount(接口(interface)的基类)可以在主应用程序中实现(并从中导出)。然后你的所有模块都需要链接到主应用程序的 lib 文件(是的!EXE 文件可以有 LIB 文件,就像 DLL 文件一样!)这就足够了。

关于C++:从 dll 动态加载类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/431533/

39 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com