Я предполагаю, что у DLL есть функция, которая освобождает структуру recipe
. Это то, что вы не можете надеяться сделать из C #. Подробнее об этом позже.
Динамический массив Delphi не является допустимым типом взаимодействия. Он действительно должен использоваться только внутри кода Delphi, скомпилированного с одной версией компилятора. Публичное раскрытие информации похоже на экспорт классов C ++ из DLL.
В идеальном мире вы бы переработали код Delphi так, чтобы он экспортировал массив, используя правильный тип взаимодействия. Тем не менее, в этом случае вам будет относительно просто выполнить сортировку без изменения кода Delphi.
Динамические массивы Delphi были введены еще в Delphi 4, и с тех пор их реализация осталась неизменной. Переменная динамического массива array of T
фактически является указателем на первый элемент. Элементы располагаются последовательно в памяти. Переменная динамического массива также поддерживает (при отрицательных смещениях) счетчик ссылок и размер массива. Вы можете спокойно их игнорировать, поскольку вы не изменяете динамический массив и не нуждаетесь в определении его размера.
Использование IntPtr
для поля Parameters
идеально. Поскольку TParameter
содержит только одно 32-разрядное целое число, вы можете использовать Marshal.Copy
, чтобы скопировать его прямо в массив int[]
.
Итак, когда DLL-библиотека Delphi возвращается, вы можете выполнить последний этап сортировки, используя Marshal.Copy
.
if (theRecipe.paramCount>0)
{
int[] parameters = new int[theRecipe.paramCount];
Marshal.Copy(theRecipe.parameters, parameters, 0, theRecipe.paramCount);
... do something with parameters
}
Это касается динамического массива, но, как это происходит, у вас есть другая проблема с вашим кодом в его нынешнем виде. Вы объявляете две строки как string
в структуре C #. Это означает, что маршаллер будет нести ответственность за освобождение памяти, возвращаемой DLL-библиотекой Delphi в двух полях PAnsiChar
. Это будет сделано путем вызова CoTaskMemFree
. Я вполне уверен, что это не будет соответствовать распределению полей PAnsiChar
, сделанных в коде Delphi.
Как указано выше, я ожидаю, что контракт для этого интерфейса заключается в том, что вы вызываете дополнительную функцию DLL для освобождения памяти кучи, на которую ссылается структура recipe
. То есть две строки и динамический массив.
Для решения этой проблемы из C # вам нужно убедиться, что маршаллер не пытается освободить поля PAnsiChar
. Вы можете добиться этого, объявив их как IntPtr
в структуре C #. Затем вызовите Marshal.PtrToStringAnsi
для преобразования в строку C #.
Мне пришлось сделать несколько предположений о контракте между кодом Delphi и кодом C #, чтобы написать выше. Если какое-либо из моих предположений неверно, обновите вопрос, и я постараюсь, чтобы этот ответ соответствовал! Надеюсь, это поможет.