什么时候将整个C 类框架放入DLL中

When to put a whole C++ class framework into a DLL?

本文关键字:DLL 框架 什么时候      更新时间:2023-10-16

我即将编写一个C 框架,以后将由不同的C 应用程序使用。该框架将提供一个主要类,该类将由应用程序实例化。该主要类将利用框架中的其他一些类。并且将有一些辅助类,该类别将直接由应用程序使用。

现在,我正在考虑如何封装该类框架。我可以像往常一样编写标题和源文件,然后在将使用该框架的应用程序中包含这些文件,以便将所有内容都与应用程序一起汇总在一起。

但我不确定这是否是"最好的"方法。将整个框架放入DLL然后将DLL链接到应用程序的选择不是一个选择吗?但是,我还读到,让DLL导出整个课程通常不是最好的主意,并且这种方法在使用STL模板作为数据成员时可能会遇到困难。

您可以向我推荐一种方法,也许我在上面没有提及的其他东西,包括。所有这些选项的优缺点?

您可以使用不透明的指针创建C接口,在您的情况下,这是需要的,因为所涉及的编译器的类型和版本。请注意,除非您还将其包裹在不透明的指针中,否则您可能不会接受或返回非C类型。这并不难,但是代表您需要一些工作。

假设一个" yourClass"类,您将创建一个包含C 类代码的您的classimpl.h和yourclassimpl.cpp(如果需要)。

yourclassimpl.h

class YourClass
{
    private:
        int value = 12345;
    public:
        YourClass() {}
        ~YourClass() {}
        int getThing() { return value; }
        void setThing(int newValue) { v = newValue}
};

然后,您将创建一个yourclass.h,它将是您的c头文件(由DLL的用户包含),其中包含不透明的指针TypeDEF和C-style接口的声明。

yourclass.h

#ifdef MAKEDLL
#  define EXPORT __declspec(dllexport) __cdecl
#else
#  define EXPORT __declspec(dllimport) __cdecl
#endif
extern "C"
{
    typedef struct YourClass *YC_HANDLE;
    EXPORT YC_HANDLE CreateYourClass();
    EXPORT void DestroyYourClass(YC_HANDLE h);
    EXPORT int YourClassGetThing(YC_HANDLE h);
    EXPORT void YourClassSetThing(YC_HANDLE h, int v);
}

在yourclass.cpp中,您将定义这些功能。

yourclass.cpp

#include "YourClass.h"
#include "YourClassImpl.h"
extern "C"
{
    EXPORT YC_HANDLE CreateYourClass()
    {
        return new YourClass{};
    }
    EXPORT void DestroyYourClass(YC_HANDLE h)
    {
        delete h;
    }
    EXPORT int YourClassGetThing(YC_HANDLE h)
    {
        return h->getThing();
    }
    EXPORT void YourClassSetThing(YC_HANDLE h, int v)
    {
        h->setThing(v);
    }
}

在您的用户代码中,它们将包括YourClass.H。

他们的code.cpp

#include "YourClass.h"
int ResetValue(int newValue)
{
    YC_HANDLE h = CreateYourClass();
    auto v = YourClassGetThing(h);
    YourClassSetThing(h, newValue);
    DestroyYourClass(h);
    return v;
}

链接到DLL的最常见方法是使用LoadLibrary/getProcaddress-我还建议在您的项目中添加.DEF文件,以确保函数命名为"好",并且由于不难而访问任何名称装饰。

一些问题要注意:

  1. 只有标准C基本类型可以在整个接口上来回传递。不要使用任何C 特定类型或类。
  2. 吊舱和吊舱阵列可能安全使用,但请注意任何包装或对齐问题。
  3. 例外不得越过接口边界 - 捕获任何被抛出的东西并将其转换为返回代码或等效。
  4. 确保在边界两侧分配的内存在同一侧进行交易。