应用程序是用delphi 2010编写的,底层的dll是C ++ DLL。
在理想情况下,当您的应用程序使用C ++时;当事件发生时,dll会对应用程序进行回调。回调是通过接口实现的。应用程序开发人员实现抽象c ++类并将对象传递给dll。然后,dll将回调您实现的类的成员函数。它是一种经典的回调模式。
但是如何将delphi对象传递给dll以使其进行回调。
答案 0 :(得分:7)
我不会称之为理想。制作一个需要消费者使用与所用DLL相同的编译器的DLL是自私和短视的。 (类布局是实现定义的,因为两个模块都需要具有相同的类概念,所以它们需要使用相同的编译器。)
现在,这并不意味着DLL的其他消费者不能伪造它。它就像DLL的设计者想要的那样容易。
当你说回调是通过接口实现的时候,你的意思是COM风格的接口,其中C ++类只有纯虚方法,包括AddRef
,Release
和{{ 1}},他们都使用 stdcall 调用约定?如果是这种情况,那么您可以简单地编写一个实现相同接口的Delphi类。在Delphi源代码和其他文献中有很多例子。
如果你的意思是你有一个非COM接口,其中C ++类只有纯虚方法,而不是三个COM函数,那么你可以编写一个具有相同布局的Delphi类。复制方法顺序,并确保所有方法都是虚拟的。 Delphi VMT与Windows实现中的大多数C ++ vtable具有相同的布局,至少就函数指针顺序而言。 (Delphi VMT也有很多非方法数据,但这不会干扰方法地址。)请确保您保持明确的所有权边界。 DLL绝不能试图破坏对象;它不会有QueryInterface
运算符可以调用的C ++可调用析构函数。
如果您的意思是您拥有可以包含数据成员,构造函数或非纯方法的任意C ++类,那么您的任务就会变得更加困难。如果是这样的话,请跟进;否则,我现在不想解决它。
总的来说,我会回应Mason的建议,即DLL应该使用普通的C风格的回调函数。一个好的经验法则是,如果您坚持使用在Windows API中看到的技术,那么您就可以了。如果您无法控制如何与DLL交互,那么就这样吧。但是,如果你可以使DLL的外部接口更像C,那将是最好的。这并不意味着你需要放弃C ++风格的界面;你可以提供两个接口,其中C风格的接口可以作为已经工作的C ++风格接口的包装。
答案 1 :(得分:3)
你不能将Delphi对象传递给C ++,至少在没有很好地理解对象模型如何在二进制级别工作的情况下。如果你需要回调,只使用C类型和普通函数和程序(没有方法),你应该没问题。