当前位置:  开发笔记 > 编程语言 > 正文

C++:从dll动态加载类

如何解决《C++:从dll动态加载类》经验,为你挑选了2个好方法。

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

我有一组定义接口的基类以及我想要加载的类的一些基本方法/成员(即用于引用计数的那些),然后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类创建的,例如Graphics-> CreateSpriteFromTexture(base :: Texture*)

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

生成的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
{
public:
    CppUtill()
    : Py::ExtensionModule("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 ++环境中使用它来解决我的问题吗?



1> Paulius..:

最简单的方法是,恕我直言,有一个简单的C函数,它返回指向其他地方描述的接口的指针.然后你的应用程序可以调用该接口的所有功能,而无需实际知道它正在使用哪个类.

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

在主应用程序代码中,为界面创建标题:

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

主app被编码为使用上面的界面,没有任何关于界面实际实现的细节.

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

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

__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函数).然后,您通过界面使用该类.

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



2> Hans Passant..:

你正在重新发明COM.您的RefCounted课程是IUnknown.您的抽象类是一个接口.DLL中的COM服务器有一个名为DllGetClassObject()的入口点,它是一个类工厂.Microsoft提供了很多关于COM的文档,稍微了解一下它们是如何做到的.

推荐阅读
依然-狠幸福
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有