Используйте PAnsiChar
вместо PChar
и integer
вместо longint/smallint
(поскольку вы используете выровненные записи, использование поля smallint не имеет смысла).
Определите некоторые типы указателей, такие как PFoo
и PBar
, которые будут написаны лучше, чем ^TFoo
, например,
Если вам нужен доступ к некоторым массивам, вы можете определить TFooArray
и TBarArray
, как показано в коде ниже.
Не забывайте cdecl
или stdcall
соглашение о вызовах для любой функции / процедуры.
type
TFoo = record
x, y : double;
a : integer;
b : PAnsiChar;
end;
TBar = record
a : double;
b : integer;
c : PAnsiChar;
end;
TFooArray = array[0..maxInt div sizeof(TFoo)-1] of TFoo;
TBarArray = array[0..maxInt div sizeof(TBar)-1] of TBar;
PBar = ^TBar;
PFoo = ^TFoo;
PFooArray = ^TFooArray;
PBarArray = ^TBarArray;
TFooBar = record
foo : PFooArray;
foo_count : integer;
bar : PBarArray;
bar_count : integer;
end;
procedure Process(const inFooBar : TFooBar); cdecl; external 'ProcessGCCLibrary.so';
Будет ли ваш процесс доступен только для чтения?
Если части C нужно добавить несколько элементов, вам нужно будет предоставить методы перераспределения памяти во внешнюю библиотеку, отображая по крайней мере reallocmem()
.
Обратите внимание, что динамические массивы Delphi можно легко отобразить в C-совместимую структуру, например:
type
TFooDynArray: array of TFoo;
TBarDynArray: array of TBar;
procedure CallProcess(const aFoo: TFooDynArray; const aBar: TBarDynArray);
var tmp: TFooBar;
begin
tmp.foo := pointer(aFoo);
tmp.foo_count := length(aFoo);
tmp.bar := pointer(aBar);
tmp.bar_count := length(aBar);
Process(tmp);
end;
Это может сделать ваш Delphi-код гораздо более читабельным. Взгляните на нашу TDynArray
оболочку , если вам нужен высокоуровневый доступ к такому динамическому массиву записей с TList
-подобными методами.
Поскольку тип AnsiString
отображает PAnsiChar
, с двоичной точки зрения вы даже можете определить свои записи так:
type
TFoo = record
x, y : double;
a : integer;
b : AnsiString;
end;
TBar = record
a : double;
b : integer;
c : AnsiString;
end;
При сопоставлении с приложением gcc оно будет читаться как обычное *char
.
Используя AnsiString
здесь вам не нужно обрабатывать выделение памяти из вашего кода Delphi. Благодаря связанному динамическому массиву это может значительно облегчить поддержку вашего кода Delphi. Обратите внимание, что наша оболочка TDynArray
будет обрабатывать вложенные AnsiString
в записях, как и ожидалось, даже для методов самого высокого уровня (например, двоичная сериализация или хеширование).