在Delphi中定义类,没有实现细节
Define class in Delphi without implementation details
我的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++类是复杂的,通常可以避免。
相关文章:
- 如果没有malloc,链表实现将失败
- 如何在c++中实现处理器调度模拟器
- 如何在c++中使用引用实现类似python的行为
- 实现无开销push_back的最佳方法是什么
- 使用简单类型列表实现的指数编译时间.为什么
- 如何在BST的这个简单递归实现中消除警告
- 实现一个在集合上迭代的模板函数
- 'using namespace'实现细节的便捷方法(仅标头库)?
- 将C++项目迁移到 Java,保护实现细节
- 如何在C++共享库中隐藏业务对象的实现细节并提供接口
- 接口,在C++中隐藏具体的实现细节
- 无锁单写多读列表的实现细节
- 为初学者澄清C++中类定义和实现的一些细节
- 在它的核心,如何实现提升元组(在提升标头中没有所有额外的细节)
- 如何查找编译器实现细节
- 循环包含在c++头文件中隐藏实现细节的技巧
- 通过减少填充头的数量来隐藏实现细节
- boost::python是如何工作的?对实现细节有什么想法吗?
- Reference_wrapper实现细节
- 内存池背后的常见实现细节是什么?