【问题标题】:Use C++ DLL callback function in a Delphi application在 Delphi 应用程序中使用 C++ DLL 回调函数
【发布时间】:2012-01-07 19:39:30
【问题描述】:

我尝试在我的 Delphi 应用程序中使用 C++ DLL 函数。我在使用这样的回调函数时遇到了问题:

C++ 中的导出函数定义:

typedef void (__CDECL__* RegisterCallBacksFunction)(AudioChunkCallBackFunction, CaptureEventCallBackFunction, LogMngr*);

回调定义:

typedef void (__CDECL__*AudioChunkCallBackFunction)(AudioChunkRef, CStdString& capturePort);
typedef void (__CDECL__*CaptureEventCallBackFunction)(CaptureEventRef, CStdString& capturePort);

AudioChunkRef 和 CaptureEventRef :

typedef boost::shared_ptr<AudioChunk> AudioChunkRef;
typedef boost::shared_ptr<CaptureEvent> CaptureEventRef;

而且 AudioChunk 和 CaptureEvent 都是 C++ 类:

class __declspec( dllexport ) AudioChunk // or CaptureEvent (both are similar)
{
public:
//some functions and variables
private:
//some functions and variables
};

C++ 库导出:

extern "C"
{
__declspec( dllexport ) void __CDECL__  RegisterCallBacks(AudioChunkCallBackFunction, CaptureEventCallBackFunction, LogMngr*);
}

如何在我的 Delphi 应用程序中使用 RegisterCallBacks 函数。 ?

【问题讨论】:

  • 查看 Rudy 的 Delphi 角,了解如何扁平化 C++ 对象接口,articles-cppobjs
  • @LURD 我不是 C++ 专家,但我怀疑 boost 类型的对象也是一种特殊类型的 C++ 类,可能需要额外的管理。

标签: c++ delphi dll callback


【解决方案1】:

AFAIK 你不能直接导入 C++ 类来映射 Delphi 类。也就是说,即使你得到一个指向AudioChunk 实例的指针,你也不能直接从Delphi 访问它。因此无法直接使用您的回调。

因此,您必须手动定义要在 Delphi 中导入的 "flat" C interface,它将在 C++ 中实现回调,然后将接口公开为 C 函数,参数为 C struct 而不是 C++ 提升类。

【讨论】:

  • 完成此操作后,您还必须为CStdStringAudioChunkRef 等找到互操作友好的替代方案。
  • 感谢 LU RD 提供了 Rudy 的文章链接。
  • 我希望 XE2 能够在 Builder C++ 和 Delphi 之间带来某种对象一致性。至少我以为我在什么地方读到过,但也许这只是一个梦。
【解决方案2】:

不同语言(如 Pascal 和 C++)的命名约定是非常复杂的话题。至少 C++ 不允许从一个供应商到另一个供应商的迁移将保留特定方法的相同导出名称。例如:Eleven@SomeClass@@QAEHXZ - 是 MSVC 的 int SomeClass::Eleven() 声明。唯一可行的方法是 C 声明,使用标准约定授予的extern "C"

但是类呢?为了避免轮子重新发明 - 对于 Delphi-C++ 使用 OLE/COM 的情况,通常您将声明接口并且可以在双方都做同样的事情。

【讨论】:

  • COM 是一个简单但不易部署的解决方案。您必须在每台 PC 上注册每个 COM 对象(或者通过代码来注册,这不再容易了);如果您通过网络运行它们,您将遇到安全问题;当您的 COM 对象更新时,您可能会遇到接口不匹配;将struct 共享为record 会有问题(VT_RECORD 类型不由 Delphi 处理,因此您必须使用接口);这是一个仅适用于 Windows 的解决方案……但尽管存在诸多困难,但它可能是一种快速实施的解决方案,并且性能良好。为 COM +1。
  • @Arnaud Bouchez - 哇,有多少问题!但一点也不。对于最简单的级别(应该由 @SimaWB 应用)COM 只是如何声明接口及其实现的合同。那里需要什么 - (1) 在 C++ 端声明类似 COM 的实现 (2) 在 Pascal 端声明存根 (3) 提供自己的 extern "C" 类似函数来创建类实例 - 并在 Pascal 端解决它。就是这样。
  • 你是完全正确的。在 C++ 代码中创建类实例将解决许多与在系统范围内注册 COM 类相关的问题。这不是我主要使用它的方式——因为我使用 COM 来处理 .Net 代码,这里我们谈论的是非托管 C++ 代码。我的错。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多