Передача двумерных массивов по ссылке между Delphi и C++
При разработке API для приложения на Delphi (XE5), возникает необходимость передачи данных между функциями DLL и основной программой, написанной на C или C++. Одним из таких случаев является передача двумерных массивов, выделенных в памяти вызовом, для заполнения их значениями из DLL.
Проблема
Использование открытых массивов (open array) в Delphi не является удобным решением для передачи двумерных массивов, так как они содержат дополнительные данные, требующие имитации в C. В связи с этим, разработчики могут рассмотреть возможность использования арифметики указателей для прямой передачи адреса массива из C в DLL.
Пример кода
Пример кода, предоставленный в вопросе, демонстрирует функцию ShowArrayContents, которая принимает указатель на массив double и размер массива, и затем перебирает его, выводит значения и перемещается к следующему элементу с помощью инкрементации указателя.
library PDA;
uses
System.StrUtils,
System.SysUtils,
Vcl.Dialogs;
{$R *.res}
function ShowArrayContents(APDouble: PDouble; size: Integer): integer; cdecl; export;
var
i: Integer;
begin
Result := 0;
for i := 0 to size-1 do
begin
// Вывод значения
MessageDlg(Format('%p -> %p -> %f', [@APDouble, APDouble, APDouble^]), mtWarning, [mbOK], 0);
Inc(APDouble);
end;
end;
exports
ShowArrayContents;
begin
end.
C-код вызывает эту функцию, передавая указатель на первый элемент двумерного массива и его размер.
В ответе было подтверждено, что предложенный код работает, но его использование неудобно. Для таких задач можно использовать директиву $POINTERMATH, которая позволяет обращаться с указателями так, как это делается в C или C++. Например:
{$POINTERMATH ON}
function GetSum(arr: PDouble; len: Integer): Double; cdecl;
var
i: Integer;
begin
Result := 0.0;
for i := 0 to len-1 do
Result := Result + arr[i];
end;
Другой подход — копирование в массив типа TArray и дальнейшая обработка:
var
x: TArray<Double>;
...
SetLength(x, len);
Move(arr^, Pointer(x)^, len*SizeOf(arr^));
Или использование цикла для копирования:
{$POINTERMATH ON}
var
i: Integer;
x: TArray<Double>;
...
SetLength(x, len);
for i := 0 to len-1 do
x[i] := arr[i];
Выводы
Передача двумерных массивов по ссылке между Delphi и C++ может быть выполнена с использованием арифметики указателей, но для более удобной и надежной работы рекомендуется использовать директиву $POINTERMATH или копирование массива в тип TArray. Выбор метода зависит от конкретных задач и предпочтений разработчика.
Передача двумерных массивов по ссылке между функциями DLL, написанными на Delphi, и основной программой на C++ для заполнения их значениями из DLL.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS