Если вы не уверены, что делаете, всегда начинайте с самого буквального перевода. Прототип функции говорит, что получает указатель на указатель на символ, поэтому вам следует использовать:
type
PTR_Allocate = procedure(param1: ^^Char; param2: ^LongWord); cdecl;
Как только вы убедитесь, что это правильно, , затем начните заменять вещи на их более Delphi-подобные эквиваленты. Если вы пропустите этот первый шаг, вы, возможно, никогда не получите его правильно, потому что вы просто будете продолжать вносить изменения в то, что начиналось неправильно.
Итак, вы уверены, что вышеприведенное верно? Не совсем. Char
в Delphi может иметь разные значения в зависимости от версии продукта. Вы используете Delphi 7, но вы можете обновить его, чтобы поделиться этим кодом с кем-то другим, поэтому вам следует четко указать, какой размер Char вы хотите. Используйте AnsiChar, когда вам нужен однобайтовый тип.
type
PTR_Allocate = procedure(param1: ^^AnsiChar; param2: ^LongWord); cdecl;
Теперь мы можем начать делать его похожим на Delphi. Один уровень параметра указателя можно заменить директивой «var» или «out». Сделайте это с каждым параметром:
type
PTR_Allocate = procedure(out param1: ^AnsiChar; var param2: LongWord); cdecl;
Указатель на AnsiChar является настолько распространенным типом, что Delphi уже имеет имя для него: PAnsiChar. Используйте идиоматическое имя:
type
PTR_Allocate = procedure(out param1: PAnsiChar; var param2: LongWord); cdecl;
И, наконец, вы, возможно, захотите взять на себя смелость и понять, что персонажи вообще задействованы. Вы четко выделяете память для произвольных байтовых буферов, поэтому байт, вероятно, является лучшим выбором, чем любой тип символов. Последние версии Delphi объявляют тип указателя на байт, поэтому используйте его:
type
PTR_Allocate = procedure(out param1: PByte; var param2: LongWord); cdecl;
Теперь перейдем к SetAllocateFunction
. Он говорит, что получает параметр PTR_Allocate
, который является указателем на функцию. Типы процедур Delphi являются неявно указателями, поэтому тип, который мы объявили выше, уже в точности соответствует Delphi-эквиваленту. Не передавайте его по ссылке с помощью дополнительной директивы «var», иначе у вас возникнут проблемы, даже до того, как ваша программа попытается выделить какую-либо память. Это то, что другие ответы упустили из виду.
procedure SetAllocateFunction(param: PTR_Allocate); cdecl;
Не добавляйте подчеркивание в начале имени, если только вы не хотите, чтобы затрудняло вызов вашего собственного кода. Если он экспортируется из DLL с другим именем, то при написании реализации функции используйте предложение «name»:
procedure SetAllocateFunction; extern 'foo.dll' name '_SetAllocateFunction';
Наконец, как реализовать функцию распределения. Начните с чего-то, что соответствует сигнатуре для PTR_Allocate, а затем продолжайте и реализуйте это, используя как можно более буквальный перевод из исходного кода C ++.
procedure Allocate(out pbuffer: PByte; var psize: LongWord; cdecl;
begin
psize := psize * 2;
GetMem(pbuffer, psize);
end;
Вы можете установить его с помощью функции:
SetAllocateFunction(Allocate);
Обратите внимание, что мне не нужна отдельная переменная, и я не использовал оператор @
. Если вам нужно использовать оператор @
для упоминания указателя на функцию, в большинстве случаев вы делаете это неправильно. Тебе обычно это не нужно. Использование этого оператора может скрыть ошибок в вашей программе, таких как несоответствия сигнатур, поскольку по умолчанию для оператора @
используется нетипизированный . Его использование удаляет тип из указателя на функцию, а нетипизированные указатели совместимы со всем в Delphi, поэтому они подходят для любого другого типа указателя на функцию, в том числе с неправильными подписями.
Используйте @
только для указателя на функцию, когда компилятор уже указал, что он попытался вызвать функцию, например, указав, что у вас недостаточно параметров, или упомянув функцию тип возврата.