代码之家  ›  专栏  ›  技术社区  ›  Vhaerun

导出DLL C++类,关于.DEF文件的问题

  •  2
  • Vhaerun  · 技术社区  · 16 年前

    我想在我的项目中使用隐式链接,nmake真的想要一个.def文件。问题是,这是一个类,我不知道在导出部分写什么。 有人能给我指个方向吗?

    错误消息如下:

    nmake:u1073:不知道如何生成“dllclass.def”

    P.S:我正在尝试使用WindowsCE平台生成器进行构建。

    4 回复  |  直到 14 年前
        1
  •  4
  •   xtofl Adam Rosenfield    16 年前

    通过使用 dumpbin /符号myclass.obj

    以我为例

    class A {
       public:
         A( int ){}
    };
    

    这个 dumpbin dump显示了符号 ??0A@@QAE@H@Z (public: __thiscall A::A(int))

    将此符号放入.def文件会导致链接器在导出符号中创建A::A(int)符号。

    但是! 正如@paercebal在他的评论中所说的那样:手工输入修饰的(损坏的)名称很容易出错,而且很遗憾,不能保证在编译器版本之间是可移植的。

        2
  •  8
  •   Greg Hewgill    16 年前

    如果我记错了,你可以用 __declspec(dllexport) 和vc++将自动为与类相关的所有符号(构造函数/析构函数、方法、vtable、typeinfo等)创建导出。

    微软对此有更多信息 here .

        3
  •  4
  •   Allbite    14 年前

    我找到了成为一家抽象工厂的最佳途径。

    首先定义一个纯粹的虚拟基类。这是一个没有实现的类,纯虚拟接口类。

    您可以导出这个虚拟基“抽象接口”类,但没有真正的理由这样做。当调用者使用它时,他们将通过一个指针(pimpl或指向实现的指针)来使用它,因此调用者所知道的只是一个简单的内存地址。一个def文件,虽然需要做更多的工作来跟上,但它提供的好处远远超出了declspec(dllexport)所能达到的。你会问什么好处?我们会解决的,你等着。

    让真正的类公开地从虚拟基继承。现在创建一个工厂方法来构造对象和 释放 “ish可调用析构函数执行清理。把这些方法命名为 构造类 “和” 释放类 “。请更换” 类名 “-”

    如果需要任何参数(简单的旧数据:整数、字符等),那么这些工厂/发布方法应该只采用pod类型。返回类型应该是虚拟抽象接口基类——或者更确切地说,是指向它的指针。

    imyclass*创建对象类型imyclass();

    也许现在很明显我们为什么需要虚拟基类?由于虚拟接口类没有实现,它本质上是所有POD类型(排序),因此类的“数据类型”可以被大多数调用方理解,如VisualBasic、C或非常不同的C++编译器。

    如果你有足够的想象力,你就可以摆脱对 手动释放 “方法(抱歉,必须这么做)。怎样?通过智能指针和PIMPL类型的体系结构来管理类中您自己的资源,这样当对象死亡时,它将自己清理掉。这样做意味着你的班级,用我们圣人和救世主不朽的话来说 Scott Meyers, " easy to use correctly and hard to use incorrectly " 让呼叫者忽略清理的必要性。让我们当中那些从未忘记打电话的人 关闭 “铸造第一块石头。

    也许这个建筑听起来很熟悉?它应该,基本上是一个微机械版的COM。嗯,至少是接口、工厂构造和发布的概念。

    最后,您已经导出了类的接口,made(和exported) 创造 破坏 方法,现在调用方可以调用 请解释类 工厂函数使您的dll在其接口的伪装下返回一个完全构造、完全实现和完全烘焙的对象。它们可以调用类中的所有公共方法(至少是抽象虚拟接口中的公共方法),并完成所有有趣的工作。

    当它们完成工厂函数返回的对象时,它们可以调用 释放类 函数要求您的dll清理对象的资源,或者您可以通过使类自己清理来帮助它们,使 释放类 “方法多余无用。

    如果有人对使用def文件和接口的具体收益和折衷感兴趣(除了我的瞎子说的那样),请竖起管道,我们可以更深入地挖掘。

    你不喜欢这些东西吗?

        4
  •  0
  •   Vhaerun    16 年前

    解决方案如下:

    • 由于类是导出的,因此还需要将导出的方法添加到.def文件中。

    • 我不知道如何导出构造函数,所以我使用了工厂方法(static),它将返回对象的新实例。

    • 其他函数将通过在.def文件中添加普通的导出声明来导出。

    希望有人能从中受益。