在Delphi中定义类,没有实现细节

Define class in Delphi without implementation details

本文关键字:实现 细节 Delphi 定义      更新时间:2024-05-10

我的Delphi应用程序使用C++DLL,该DLL内部使用第三方库(也是用C++编写的(。有一个来自第三方库的类,我想在Delphi应用程序中使用它。我们有来自第三方库的标头。

其想法是通过CALLBACK将指向此类实例的指针传递给Delphi应用程序。该对象将只在Delphi中使用,但从未在那里实现。

C++类的精简版本是:

class XImage
{
public:
XImage() {}
~XImage() {}
inline uint32_t GetPixelVal(uint32_t row, uint32_t col) {...}
uint32_t    _height;
uint32_t    _width;
uint32_t    _pixel_depth;
uint8_t*    _data_;
};

我想尽我所能在Pascal:中定义这个类

TXImage = class
public
constructor Create();
destructor Destroy();
DWORD GetPixelVal(DWORD row, DWORD col);
DWORD   _height;
DWORD   _width;
DWORD   _pixel_depth;
BYTE*   _data_;
end;

但这会导致编译失败,原因是"不满意的转发或外部声明"。

有没有任何方法可以定义类的接口,使其在Delphi中可用,但不需要提供实现细节?

Rudy Velthuis提出的扁平化方法奏效了,但我设法以其他Delphi开发人员可能感兴趣的方式解决了这个问题。这种方法之所以有效,是因为所需的数据(_height_width_data_(已在C++类中定义为公共数据。

步骤1:定义一个自定义结构来保存C++类中的数据。

// C++
typedef struct
{
WORD width, height;
BYTE* pBits;
} TXIMAGE, *PTXIMAGE;
// Delphi
PTXIMAGE = ^TXIMAGE;
TXIMAGE = record
width, height: WORD;
pBits: PBYTE;
end;

步骤2:定义一个回调原型,用于从C++到Delphi的通信。

// C++
typedef void (*CALLBACK_FRAME_READY)(PTXIMAGE);
// Delphi
TExternalProcCallback = procedure(image: PTXIMAGE); stdcall;

步骤3:使用C++DLL注册回调。

// Delphi
procedure RegisterCallbackFrameReady(callback: TExternalProcCallback); stdcall;
// ...
procedure RegisterCallbackFrameReady; external 'MyDLL.dll' name '_RegisterCallback@4'; stdcall;
// ...
RegisterCallbackFrameReady(SomeFunction);
// C++
void DETECTOR_COMMS_API RegisterCallback(CALLBACK_FRAME_READY pCallback)
{
// Save this function pointer as member data...
CALLBACK_FRAME_READY frameCallback = pCallback;
}

步骤4:当您的C++对象需要在Delphi中处理时,调用回调。

// C++
TXIMAGE m_frame;
m_frame.width = static_cast<WORD>(image_->_width);
m_frame.height = static_cast<WORD>(image_->_height);
m_frame.pBits = image_->_data_;
if (frameCallback)
frameCallback(&m_frame);

步骤5:在Delphi 中处理数据

procedure SomeFunction(image: PTXIMAGE); stdcall;
var
Value, ValueMin, ValueMax: BYTE;
x, y: WORD;
pPixels: PBYTE;
begin
// Detector frame!
// Generate some frame diganostics
Value := 0;
ValueMin := High(WORD);
ValueMax := Low(WORD);
pPixels := image.pBits;
for y:=0 to (image.height - 1) do
begin
for x:=0 to (image.width - 1) do
begin
Value := pPixels^;
if (Value < ValueMin) then
ValueMin := Value;
if (Value > ValueMax) then
ValueMax := Value;
Inc(pPixels);
end;
end;
end;

效果很好。正如Rudy Velthuis的文章和评论中所说,试图导出C++类是复杂的,通常可以避免。