Определить класс в Delphi без подробностей реализации - PullRequest
0 голосов
/ 03 мая 2020

My Delphi приложение, использующее C ++ 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, но без необходимости предоставления деталей реализации?

1 Ответ

0 голосов
/ 06 мая 2020

Метод выравнивания , предложенный Руди Велтуисом , сработал, но мне удалось решить проблему таким образом, который может заинтересовать других Delphi разработчиков. Этот подход работает, потому что необходимые данные (_height, _width и _data_) были определены как publi c в классе 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 ++ является сложной и часто ее можно избежать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...