简体   繁体   English

从C ++ dll回调到delphi应用程序

[英]Callback from a C++ dll to a delphi application

Application is written in delphi 2010 and the underlying dll is a C++ dll. 应用程序是用delphi 2010编写的,基础dll是C ++ dll。

In ideal case, when your application is in C++; 在理想情况下,当您的应用程序是C ++时; The dll makes a callback to an application when an event occurs. 事件发生时,dll会回调应用程序。 The callback is implemented through an interface. 回调是通过接口实现的。 Application developers implements the abstract c++ class and pass the object to the dll. 应用程序开发人员实现抽象的c ++类,并将对象传递给dll。 The dll will then make a callback to a member function of your implemented class. 然后,dll将对实现的类的成员函数进行回调。 A classic callback pattern it is. 这是一个经典的回调模式。

But how do I pass a delphi object to the dll for it to make a callback. 但是我如何将一个delphi对象传递给dll来进行回调。

I wouldn't really call that ideal. 我真的不会叫那个理想。 It is selfish and short-sighted to make a DLL that requires its consumers to use the same compiler as the DLL used. 制作要求其使用者使用与所用DLL相同的编译器的DLL是自私的并且是短视的。 (Class layout is implementation-defined, and since both modules need to have the same notion of what a class is, they need to use the same compiler.) (类布局是实现定义的,并且由于两个模块都需要对类的概念相同,因此它们需要使用相同的编译器。)

Now, that doesn't mean other consumers of the DLL can't fake it. 现在,这并不意味着DLL的其他使用者无法伪造它。 It just won't be as easy for them as the DLL's designer intended. 对于他们来说,这将不会像DLL的设计者那样容易。

When you say the callback is implemented through an interface, do you mean a COM-style interface, where the C++ class has nothing but pure virtual methods, including AddRef , Release , and QueryInterface , and they all use the stdcall calling convention? 当您说回调是通过一个接口实现的时,您的意思是一个COM样式的接口,其中C ++类除纯虚拟方法外没有其他东西,包括AddRefReleaseQueryInterface ,它们都使用stdcall调用约定? If that's the case, then you can simply write a Delphi class that implements the same interface. 如果是这种情况,那么您可以简单地编写一个实现相同接口的Delphi类。 There are many examples of that in the Delphi source code and other literature. Delphi源代码和其他文献中有许多示例。

If you mean you have a non-COM interface, where the C++ class has only pure virtual methods, but not the three COM functions, then you can write a Delphi class with the same layout. 如果您是说您有一个非COM接口,其中C ++类仅具有纯虚拟方法,而没有这三个COM函数,则可以编写具有相同布局的Delphi类。 Duplicate the method order, and make sure all the methods are virtual. 复制方法顺序,并确保所有方法都是虚拟的。 The Delphi VMT has the same layout as most C++ vtables on Windows implementations, at least as far as the function-pointer order is concerned. Delphi VMT的布局与Windows实现上的大多数C ++ vtable相同,至少就功能指针顺序而言。 (The Delphi VMT has a lot of non-method data as well, but that doesn't interfere with the method addresses.) Just be sure you maintain clear ownership boundaries. (Delphi VMT也有很多非方法数据,但这不会干扰方法地址。)请确保您保持明确的所有权边界。 The DLL must never attempt to destroy the object; DLL绝不能尝试销毁对象。 it won't have a C++-callable destructor that the delete operator could invoke. 它没有delete运算符可以调用的C ++可调用析构函数。

If you mean that you have an arbitrary C++ class that could include data members, constructors, or non-pure methods, then your task is considerably more difficult. 如果您的意思是您有一个任意的C ++类,其中可能包含数据成员,构造函数或非纯方法,那么您的任务就困难得多。 Follow up if this is the case; 如果是这种情况,请跟进; otherwise, I'd rather not address it right now. 否则,我宁愿现在不解决。

Overall, I'll echo Mason's advice that the DLL should use plain C-style callback functions. 总的来说,我会回应梅森的建议,即DLL应该使用纯C风格的回调函数。 A good rule of thumb is that if you stick to techniques you see in the Windows API, you'll be OK. 一个好的经验法则是,如果您坚持使用Windows API中的技术,就可以了。 If you're not in control of how to interact with the DLL, then so be it. 如果您无法控制与DLL的交互方式,那就去吧。 But if you can make the DLL's external interface more C-like, that would be best. 但是,如果您可以使DLL的外部接口更像C,那将是最好的。 And that doesn't mean you need to abandon the C++-style interface; 但这并不意味着您需要放弃C ++风格的接口; you could provide two interfaces, where the C-style interface serves as a wrapper for your already-working C++style interface. 您可以提供两个接口,其中C样式接口用作已经工作的C ++样式接口的包装。

You can't pass a Delphi object to C++, at least not without a very good understanding of how the object model works at the binary level. 您不能将Delphi对象传递给C ++,至少不能很好地了解对象模型在二进制级别的工作方式。 If you need callbacks, do them using C types only and plain functions and procedures (no methods) and you should be fine. 如果您需要回调,请仅使用C类型以及简单的函数和过程(无方法)进行回调,您应该会满意。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM