【问题标题】:exporting classes to DLLs [duplicate]将类导出到 DLL [重复]
【发布时间】:2011-07-08 06:39:20
【问题描述】:

你好,我现在对 DLL 有点困惑,所以我来这里询问编程方面有很多专业人士 所以我得到了这个名为 GUI.h 的类和 GUI.cpp

class GUI
{
    public:
        GUI(void);
        virtual ~GUI();
        void Draw(float x,float y,float z);
        void Texture(int num);
        bool Shutdown();
        void TextureON(int num);
        void TextureOFF(int num);

    private:
    GUIWeapon * Weapon;
    GUIWeaponA * Weapona;
    GUIArrow * Arrow;
    GUIHP * hp;
    GUIStop * stop;
    GUISpeed * Speed;
    float XCam,YCam,ZCam;
    bool DrawStop;

};

那么我应该如何将它导出到一个我已经制作 DLL 但不使用类的 DLL 那么我应该如何声明构造函数、析构函数并在其他头文件中调用其他 GUIFunction?

【问题讨论】:

标签: c++ dll


【解决方案1】:

您无需指定编译器或操作系统,但如果这是 Windows 和 Microsoft C++,那么您可以在类上使用 __declspec(dllexport) 从 DLL 导出它。然后,当您包含要在其他地方使用的标头时,您可以在同一类上使用 __declspec(dllimport)。

但是,我倾向于建议不要从 DLL 导出类。如果所有 DLL 总是一起发布并一起构建,这是一个不错的计划。 [DLL 仅用于延迟加载代码]。如果您使用 DLL 来提供单独发布的实际组件,则应使用实际的可版本化抽象,如 COM。

马丁

【讨论】:

  • 好的,非常感谢你,我也反对它,但这真的是我现在没有做的功课,哈哈
  • @Makenshi:那就下次用homework标签
【解决方案2】:

像这样导出:

class __declspec(dllexport) GUI 
{...}

像这样导入:

class __declspec(dllimport) GUI 
{...}

或者简单地定义一个这样的宏:

#if _DEFINE_THIS_IN_YOUR_DLL_
    #define CLASS_IMPORT_EXPORT __declspec(dllexport)
#else
    #define CLASS_IMPORT_EXPORT __declspec(dllexport)
#endif

并直接使用:

class CLASS_IMPORT_EXPORT GUI
{
};

确保 DLL 及其客户端都具有 SINGLE 头文件。

但需要注意的是,您在 DLL 中的 sizeof 类和客户端 (EXE) 必须相同。例如,您可能有一个定义为宏的 SOME_SIZE 数组。在 DLL 中,它可能是 100,但在 EXE 中它可能是 200(无论出于何种原因)。这只会破坏类,当您调用某些函数时,this 指针将是正确的;但不是班级(这意味着sizeof(GUI-in-DLL) != sizeof(GUI-in-EXE)

导出一个类也意味着公开包含它的所有数据成员。这意味着公开所有其他类/结构/typedef/私有变量等等。对于解决方案,可以计算所有数据成员的大小(比如 154 字节),并在类声明中声明 char filler[154](用于隐藏实际数据)。 虽然这实际上可行,但编译器链接器、调试器等不会有任何问题 - 但对程序员来说并不灵活。

无论是否使用填充字节隐藏实际数据声明,您还必须确保 #pragma 打包。一方面,如果 DLL 有 4 个字节的打包,而 EXE 有(甚至是错误的)1 个字节的打包,那么你就一团糟。而且这个错误/bug很难被发现!

IMO 最好的解决方案是导出一个类,该类具有指向实现实际功能的类的指针。这意味着 GUI_Internal/GUI_Core 并仅导出 GUI 具有以下任一类的指针:

class IMPORT_EXPORT GUI
{
   GUI_Internal* pInternal; // 4/8 bytes only! EXACT
   // ... Export functions
};

但这需要 DLL 的客户端(在编译器级别)知道GUI_Internal 是什么。为此,只需一个typedef

#if _DEFINE_THIS_IN_YOUR_DLL_
typedef GUI_Internal* ClassPointer;
#else
typedef void* ClassPointer
#endif

并使用它:

class CLASS_IMPORT_EXPORT GUI 
{ 
ClassPointer pointer; // Name is something else! ... 
};

这显然需要您分配带有 GUI_Internal 实例的指针,并将函数转发给该类。

【讨论】:

    猜你喜欢
    • 2013-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多