Передача параметров из Delphi 5 в Delphi DLL XE

#delphi

#delphi

Вопрос:

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

основное приложение

   function Modulo_Pptos_Operacion(No_Orden : Integer; pathBD : string; PathBDConf :   String) : Integer ; stdcall;
 external 'LIB_Pptos_Oper.dll';

  Modulo_Pptos_Operacion(DmDatos.OrdenesNO_Orden.AsInteger,
   DmDatos.CiasPATHA.AsString, 'Alguna String');
 

DLL

   Modulo_Pptos_Operacion function (No_Orden: Integer; PathDB: AnsiString; PathDBConfig: AnsiString): Integer; StdCall;
 

ДИНАМИЧЕСКИЙ СБОЙ
основного приложения

   type
    TDLLPpto = function(No_Orden : Integer; PathDB : AnsiString; PathDBConfig : AnsiString) : Integer;
  var
    DLLHandle: THandle;
    : TDLLPpto;

  PROCEDURE CALL
    DLLHandle := LoadLibrary('LIB_Pptos_Oper.dll');
    DLLHandle <> 0 then
   begin
     @DLLPpto := GetProcAddress(DLLHandle, 'Modulo_Pptos_Operacion');
   end;
  ;
 

какой правильный путь?

Ответ №1:

Проблема, вероятно, в том, что вы смешиваете разные среды выполнения и, вероятно, разные кучи. Строки Delphi не являются допустимыми типами взаимодействия, поскольку их реализации варьируются от версии к версии.

В этом случае вы можете просто переключиться на использование строк с нулевым завершением, PAnsiChar .

Комментарии:

1. Точно. AnsiString НИКОГДА не бывает безопасным, даже если вы не смешиваете версии delphi, если только и основной EXE, и DLL не используют общую память (borlandmm.dll ) диспетчер памяти.

Ответ №2:

В случае динамически загружаемой dll вы пропустили stdcall; директиву соглашения о вызове в объявлении TDLLPpto . Тем не менее, рекомендуется использовать PAnsiChar type для передачи строк через границы исполняемого файла.

Комментарии:

1. Это не только желательно, но и часто бывает нестабильным, если вы этого не сделаете. Приготовьтесь к случайной ошибке.

Ответ №3:

Макет ansistring изменился с Delphi XE: теперь также есть поле кодовой страницы с отрицательным смещением, а в D5 его нет. НАПРИМЕР: строки из D5 и DXE совершенно несовместимы. Таким образом, вы должны использовать PAnsiChar или PWideChar в своем интерфейсе, либо заканчивающийся нулем (строки Delphi всегда заканчиваются нулем), либо ввести дополнительный параметр с длиной, если строка может содержать # $ 00 байт.

Также: разные версии Delphi имеют разные менеджеры памяти. Если строка выделяется основным приложением и освобождается библиотекой DLL (строки подсчитываются по ссылкам), указатель get передается неправильному менеджеру памяти, что обычно приводит к повреждению памяти и, следовательно, к неприятным нарушениям доступа и т.д.

Другим решением является использование WideString ; это как в D5, так и в DXE равно COM BSTR stringtype и управляется ОС, а не менеджером памяти Delphi. Они совместимы. Единственная проблема в том, что они медленные по сравнению со строками Delphi и не учитываются ссылки.

В целом: при использовании интерфейсов DLL старайтесь избегать string, используйте PAnsiChar или PWideChar, или WideString

Комментарии:

1. WideString также является отличным выбором, который я опустил в своем ответе. Я сомневаюсь, что производительность WideString vs UnicodString/AnsiString здесь имеет значение.

2. @David: Я тоже в этом сомневаюсь, но эти ответы также читаются другими из-за их проблем, и обычно такая информация имеет значение ;-).