Использование C ++ DLL в Delphi 6

Я должен использовать функцию кодирования из внешней C ++ DLL в Delphi 6.
Ниже приводится декларация:

long <Function Name> (char *Data, long &Apply, char *ReturnVal, long &Size)

Данные — это входное значение, Apply — логическое значение (по умолчанию: FALSE), ReturnVal — это возвращаемое значение из DLL, а Size — длина ReturnVal.

Чтобы использовать это в Delphi 6, я написал следующий код:

implementation
const
EncoderDLL = '<DLL NAME>';
FunctionName = 'FUNCTION NAME';
var
_TEST : function(const Data : PChar; Apply : PInteger;stOutput : Pchar;
iSize : PInteger) : integer; stdcall;
.....
.....
var
stInput,stOutput : string;
iLength,i1,iResult : integer;
hnd : THandle;
begin
iLength := 0;
i1 := 0;
stInput := Trim(edtInput.Text);
hnd := SafeLoadLibrary(EncoderDLL);
if hnd > 0 then
begin
@_TEST := GetProcAddress(hnd,FunctionName);
if @_TEST <> nil then
begin
iResult := _TEST(PChar(stInput),@i1,PChar(StOutput),@iLength); // ERROR
end;
end;
FreeLibrary(hnd);
end;

я получаю Нарушение доступа в строке с ошибкой в ​​качестве комментариев.

Если я заменю PChar в объявлении функции с строка, тогда нарушение доступа не происходит на той же линии. Это происходит при освобождении библиотеки. Также значение параметра iLength заполняется правильно.

Может кто-нибудь, пожалуйста, предоставьте указатели для решения этой проблемы.

1

Решение

Сохраните PChar и инициализируйте StOutput непустой строкой (достаточной длины) перед вызовом.

2

Другие решения

  1. Ты уверен насчет конвенции stdcall? Если в тексте C ++ нет четких инструкций (например, WINAPI, __stdcall и т. Д.), Используйте cdecl.

  2. «const» до того, как данные не нужны

  3. выделить память для StOutput

3

Я предполагаю, что ReturnVal является выходным параметром (функция заполняет его). Вы должны зарезервировать память для этой строки в вашем коде. Но сколько памяти вы должны зарезервировать? Существует общая схема для таких функций. Вы вызываете функцию дважды.

в первый звонок Ты устанавливаешь ReturnVal в nil и функция заполняет в каком размере она нуждается в Size параметр.

Затем вы сохраняете столько памяти в вашем StOutput буфера и вызовите функцию снова. На этот раз вы получите результат.

iResult := _TEST(PChar(stInput),@i1,nil,@iLength); // First call
SetLength( stOutput, iLength ); // reserve memory
iResult := _TEST(PChar(stInput),@i1,PChar(stOutput),@iLength); // Second call

Обратите внимание, что эта функция может или не может следовать этому соглашению. Но если этого не произойдет, то на самом деле нет способа определить, сколько памяти следует зарезервировать для выходного параметра.

Еще одна вещь, которую стоит отметить, это соглашение о вызовах. Функции C и C ++ по умолчанию cdecl и декларация, которую вы показали, не говорит иначе. Вы объявили это как stdcall в Паскале. Они должны совпадать.

3
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector