При работе с внешними библиотеками в Delphi, особенно при переводе функций, написанных на C++, часто возникают проблемы, связанные с непониманием того, как обходятся строки и указатели в этих языках. В данной статье рассмотрим типичные ошибки, возникающие при использовании функций, экспортируемых из DLL, на примере функции MY_GetDLLInfo, написанной на C++ и предназначенной для вызова из Delphi 7.
Проблема
Рассмотрим код на C++, который экспортирует функцию MY_GetDLLInfo для получения информации о DLL:
var
hHandle: THandle;
p_version, p_release_type, p_build_date, p_load_path: PPAnsiChar;
begin
hHandle := LoadLibrary(Dl_path);
@MY_GetDLLInfo := GetProcAddress(hHandle, PChar('MY_GetDLLInfo'));
if Assigned(MY_GetDLLInfo) then begin
MY_GetDLLInfo(p_version, p_release_type, p_build_date, @null);
ShowMessage(StrPas(@p_version));
ShowMessage(StrPas(@p_release_type));
ShowMessage(StrPas(@p_build_date));
end;
end;
При выполнении этого кода пользователь сталкивается со странным выводом, предполагая, что проблема может быть связана с использованием функции StrPas.
Решение проблемы
В C/C++ char* соответствует PAnsiChar в Delphi, а char** соответствует PPAnsiChar. Это означает, что локальные строковые переменные должны быть объявлены как PAnsiChar, а не как PPAnsiChar, и для передачи их в функцию необходимо использовать оператор @ для получения их адресов.
Также важно отметить, что в Delphi для обозначения null используется nil. Вот исправленный пример вызова функции в Delphi:
// Delphi Call Example
var
hHandle: THandle;
MY_GetDLLInfo: function(const pp_version, pp_release_type, pp_build_date, pp_load_path: PPAnsiChar): Integer; stdcall;
p_version, p_release_type, p_build_date: PAnsiChar;
begin
hHandle := LoadLibrary(Dl_path);
if hHandle <> 0 then
begin
@MY_GetDLLInfo := GetProcAddress(hHandle, 'MY_GetDLLInfo');
if Assigned(MY_GetDLLInfo) then
begin
p_version := nil;
p_release_type := nil;
p_build_date := nil;
MY_GetDLLInfo(@p_version, @p_release_type, @p_build_date, nil);
ShowMessage(p_version);
ShowMessage(p_release_type);
ShowMessage(p_build_date);
end;
FreeLibrary(hHandle);
end;
end;
Заключение
При работе с внешними функциями, написанными на C++, важно правильно понимать типы данных и способы их передачи. В Delphi для работы со строками и указателями используются типы PAnsiChar и PPAnsiChar, соответственно, а для передачи указателей — оператор @. Правильное использование этих элементов позволит избежать большинства ошибок, связанных с некорректной работой с указателями и строками при вызове функций из DLL в Delphi.
Проблема связана с некорректной работой указателей и строк в коде Delphi при взаимодействии с функциями из C++ библиотеки.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.