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

时间:2008-10-09 07:13:55

标签: c++ build windows-ce nmake function

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

错误消息如下:

NMAKE:U1073:不知道如何制作'DLLCLASS.def'

P.S:我正在尝试使用Windows CE Platform Builder构建。

4 个答案:

答案 0 :(得分:8)

如果我没记错,你可以在上使用__declspec(dllexport),VC ++会自动为与该类相关的所有符号创建导出(构造函数/析构函数,方法,vtable, typeinfo等。)

Microsoft提供了有关此here的更多信息。

答案 1 :(得分:4)

您始终可以使用dumpbin / symbols myclass.obj

找到成员函数的修饰名称

在我的情况下

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

dumpbin转储显示符号??0A@@QAE@H@Z (public: __thiscall A::A(int))

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

但是!正如@paercebal在评论中指出的那样:装饰(受损)名称的手动输入是一件苦差事 - 容易出错,而且很遗憾,不能保证在编译器版本之间可移植。< / p>

答案 2 :(得分:4)

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

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

您可以导出此虚拟基础“抽象接口”类,但没有真正的理由这样做。当调用者使用它时,他们将通过指针(PImpl,或指向实现的指针)使用它,因此所有调用者都知道的是一个简单的内存地址。 Def文件虽然需要花费十分多的工作量,但它提供的优势超出了__declspec(dllexport)所能达到的效果。你问什么好处?我们会接受,你只是等待。

让您的真正的班级公开继承自虚拟基地。现在创建一个构造对象的工厂方法和一个“ release ”ish可调用析构函数来执行清理。将这些方法命名为“ ConstructMyClass ”和“ ReleaseMyClass ”。请更换“ MyClass ”: - )

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

IMyClass * CreateAnObjectOfTypeIMyClass();

现在可能很明显为什么我们需要虚拟基类?由于虚拟接口类没有实现,它基本上都是所有POD类型(排序),因此大多数调用者可以理解类的“数据类型”,如Visual Basic,C或完全不同的C ++编译器。

如果你有足够的想象力,你可以解决“手动发布”方法的需要(抱歉,必须这样做)。怎么样?通过智能指针和pImpl类型的体系结构管理类中的自己的资源,这样当对象死亡时,它将自行清理。这样做意味着你的班级,在我们的圣徒和救世主Scott Meyers, "easy to use correctly and hard to use incorrectly"的不朽言辞中,让呼叫者无视清理的需要。让那些从未忘记称之为“ .close ”的人投下第一块石头。

也许这个架构听起来很熟悉?应该,它基本上是COM的微机械版本。好吧,至少是界面,工厂建设和发布的概念。

最后,您已经为您的类导出了界面,制作(并导出)创建销毁方法,现在调用者可以调用您的 PleaseConstructMyClass 工厂函数让你的DLL在其界面的幌子下返回一个完全构造,完全实现和完全烘焙的对象。他们可以调用你班级的所有公共方法(至少是抽象虚拟界面中的方法),并做所有有趣的事情。

当他们完成工厂函数返回的对象时,他们可以调用“ ReleaseMyClass ”函数来让你的DLL清理对象的资源,或者你可以帮助他们通过让你的类自己清理,使“ ReleaseMyClass ”方法变得冗余无用。

如果有人对特定的收益和兴趣感兴趣使用Def文件和界面的权衡(除了我的盲目说法),请加油,我们可以深入挖掘。

难道你不喜欢这个东西吗?

答案 3 :(得分:0)

解决方案如下:

  • 因为导出了类,所以还需要在.def文件中添加导出的方法

  • 我没有找到如何导出构造函数,所以我使用了一个工厂方法(静态),它将返回一个对象的新实例

  • 通过在.def文件中添加常规导出声明来导出其他函数

希望有人能从这些信息中受益。