При работе с компонентами Devart IBDac в Delphi 10.1 для реализации функций резервного копирования и восстановления базы данных Firebird в установщике Inno Setup возникла проблема, связанная с переходом на использование Unicode. В данной статье мы рассмотрим, почему использование String в качестве параметров для функций DLL привело к ошибкам и как их можно решить.
Описание Проблемы
Разработчик столкнулся с проблемами при использовании Unicode версии Inno Setup 5.5.9 совместно с DLL, созданной в Delphi 10.1. После изменения типов параметров с AnsiString/PAnsiChar на String в DLL и скрипте Inno Setup, начались сбои в работе, не связанные с передачей параметров, например, при использовании функции Trim или создании объекта DBConnection.
Подтвержденный Ответ
Проблема заключалась в использовании типа String в DLL, который не совместим с прохождением границы DLL. String в Delphi является "умным" типом, который управляет выделением памяти и подсчетом ссылок, что невозможно для DLL, так как каждая сторона имеет свой менеджер памяти.
Альтернативный Ответ
Для решения проблемы необходимо использовать тип PWideChar в Delphi и объявлять параметры как (широкие) строки в Unicode версии Inno Setup. Использование PWideChar не представляет неудобств для аргументов, передаваемых в DLL.
Пример Кода
{$MODE OBJFPC}
{$H+}
library Sample;
uses
SysUtils;
function GetSampleString(Buffer: PWideChar; NumChars: DWORD): DWORD; stdcall;
var
OutStr: UnicodeString;
begin
OutStr := 'sample output string';
if Assigned(Buffer) and (NumChars >= Length(OutStr)) then
StrPCopy(Buffer, OutStr);
result := Length(OutStr);
end;
exports
GetSampleString;
end.
Используйте функцию GetSampleString дважды: сначала для получения необходимой длины строки, а затем для копирования строки в буфер.
В коде Inno Setup:
function GetSampleString(Buffer: string; NumChars: DWORD): DWORD;
external 'GetSampleString@Sample.dll stdcall';
function SampleString(): string;
var
NumChars: DWORD;
OutStr: string;
begin
result := '';
NumChars := GetSampleString('', 0);
SetLength(OutStr, NumChars);
if GetSampleString(OutStr, NumChars) > 0 then
result := OutStr;
end;
Заключение
Переход на использование широких строк в Inno Setup и Delphi 10.1 требует внимательного отношения к типам данных и их совместимости между различными компонентами системы. Применение PWideChar вместо String позволит избежать проблем с памятью и менеджерами памяти, что является ключом к успешному решению описанной проблемы.
В статье обсуждается проблема совместимости строк в Unicode между Inno Setup и Delphi 10.1 при использовании компонентов Devart IBDac для функций резервного копирования и восстановления баз данных Firebird, и предлагается решение с использованием широких
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS