【发布时间】:2016-03-23 00:09:43
【问题描述】:
我需要从 Delphi 调用一些 C++ 代码。作为回报,C++ 代码需要能够回调到 Delphi 代码中。此处显示的示例Calling a callback function in Delphi from a C++ DLL 运行良好。但是,我不想将单个 Delphi 函数作为回调传递给 C++,而是传递一个实现接口的 Delphi 对象。
编辑:通过接口我指的是 C++ 术语,它是一个具有纯虚函数的类。这不一定是使用 Delphi interface 关键字定义的类型。换句话说,下面的类定义了一个我想从 C++ 调用的接口:
ICallable = class
procedure callMe stdcall; virtual; abstract;
procedure CallMeAgain stdcall; virtual; abstract;
end;
ICallable 接口将依次在 Delphi 中实现如下:
MyCallable = class(ICallable)
procedure callMe override;
procedure callMeAgain override;
end;
procedure MyCallable.callMe
begin
WriteLine('I was called');
end;
procedure MyCallable.callMeAgain
begin
WriteLine('I was called again');
end;
在编译为DLL的C++端,我想定义ICallable接口如下:
class ICallable{
public:
virtual void callMe()=0;
virtual void callMeAgain()=0;
}
并导出如下DLL函数,以便Delphi调用:
#define DllExport extern "C" __declspec( dllexport )
DLLExport bool Callback(ICallable* callable){
callable->callMe();
callable->callMeAgain();
return true;
}
最后回到 Delphi:
function Callback(myCallable: ICallable) : Boolean cdecl; external 'dllname'
问题:
- 这只能工作如果 C++ 和 Delphi 以相同的方式实现它们的虚拟方法表。是这样吗?
【问题讨论】:
-
Delphi 接口遵循 COM 约定。所以你需要遵循 C++ 中的 COM 约定,参见:rvelthuis.de/articles/articles-cppobjs.html 和 scritub.com/stiinta/tutorials/visual-c-en/…
-
哦,Delphi 中的接口是使用
interface关键字声明的。如果您坚持声明非 COM 接口,请使用abstract class。接口的实现派生自TInterfacedObject。 -
Delphi 总是将 VMT 作为类中的第一个字段。 C++ 没有这样的规则。所有这些都可以在 Rudy 的文章中读到。 你读过吗?所以答案是肯定的和否定的。
-
VMT 只是一个指针数组,无论是在 Delphi 还是 C++ 中;这里没有问题。你的代码还有其他明显的问题,首先它没有实现
IUnknown。见Consuming Delphi interfaces in Dephi and C++如何解决相反的问题——写一个Delphi DLL导出一个接口并在C++端使用这个接口。 -
COM 机制只是你做以下事情: 1. 使用 Delphi 接口。 2.在Delphi代码中实现
IInterface,例如通过派生自TInterfacedObject。 3. 从IUnknown派生C++ 类。 4. 呃,就这样,没有了。