我想在我的项目中使用隐式链接,而nmake确实想要一个.def文件。问题是,这是一个类,我不知道在exports部分写什么。 有人能指出我正确的方向吗?
错误消息如下:
NMAKE:U1073:不知道如何制作'DLLCLASS.def'
P.S:我正在尝试使用Windows CE Platform Builder构建。
答案 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文件中添加常规导出声明来导出其他函数
希望有人能从这些信息中受益。