2

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

错误消息如下:

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

PS:我正在尝试使用 Windows CE Platform Builder 进行构建。

4

4 回答 4

8

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

Microsoft 在此处提供了更多信息。

于 2008-10-09T07:21:00.167 回答
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 在他的评论中所说:手动输入修饰(损坏)名称是一件苦差事——容易出错,而且很遗憾,不能保证在编译器版本之间移植。

于 2008-10-09T11:32:08.693 回答
4

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

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

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

让你的真实类从虚拟基础公开继承。现在创建一个工厂方法来构造你的对象和一个“释放”可调用的析构函数来执行清理。将这些方法命名为“ ConstructMyClass ”和“ ReleaseMyClass ”。拜托,请替换“ MyClass ” :-)

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

IMyClass* CreateAnObjectOfTypeIMyClass();

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

如果你足够花哨,你可以绕过对“手动发布”方法的需求(抱歉,不得不这样做)。如何?通过智能指针和 pImpl 类型的体系结构在类中管理您自己的资源,因此当对象死亡时,它会自行清理。这样做意味着,用我们的圣人和救世主斯科特·迈耶斯 (Scott Meyers) 的不朽名言来说,您的班级是“易于正确使用,难以正确使用,让调用者无视清理的需要。让我们中间那些从未忘记调用“ .close ”的人投下第一块石头。

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

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

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

如果有人对使用 Def 文件和界面的具体收益和权衡感兴趣(除了我的盲说),请竖起大拇指,我们可以更深入地挖掘。

你不只是喜欢这些东西吗?

于 2010-03-23T08:26:18.780 回答
0

解决方案如下:

  • 由于导出了一个类,因此还需要在 .def 文件中添加导出的方法

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

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

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

于 2008-10-09T08:39:46.857 回答