Один из способов обмена строками между вашей DLL и приложением Delphi без использования вызова FreeString - это взять строковый буфер из вызывающего приложения как PChar и заполнить буфер в DLL. Именно так работают функции API Windows, когда им нужно обмениваться строками с вызывающими приложениями.
Для этого вызывающее приложение создает строковый буфер и отправляет PChar со ссылкой на этот буфер вместе с размером буфера в вашу функцию DLL. Если размер буфера меньше, чем фактическая строковая DLL должна отправить в приложение, ваша функция DLL может отправить фактический необходимый размер буфера вызывающему приложению.
как он будет себя вести с Delphi 2010
и WideString по умолчанию: сделать
нужно форсировать WidePChar во FreePascal
тоже?
В Delphi 2009 и Delphi 2010 PChar соответствует PWideChar. В предыдущих версиях Delphi и, насколько мне известно, во FreePascal PChar равняется PAnsiChar. Поэтому, если вы вернете PChar из своей DLL, ваш код не будет работать правильно в Delphi 2010. Вам следует явно использовать PAnsiChar или PWideChar. Вы можете снова следовать функциям Windows API. Они предоставляют две версии многих функций API: одна с поддержкой WideChar, в имени которой в качестве суффикса указан символ W, а другая - с поддержкой ANSI, в имени которой в качестве суффикса используется символ A.
Объявление вашей функции DLL будет выглядеть примерно так:
function AStringFuncW(Buffer: PWideChar; var BufferSize: Integer): Boolean;
function AStringFuncA(Buffer: PAnsiChar; var BufferSize: Integer): Boolean;
EDIT:
Вот пример кода:
1- Ваша функция DLL для widechar будет выглядеть так:
function AStringFuncW(Buffer: PWideChar; var BufferSize: Integer): Boolean; stdcall;
var
MyOutputStr : WideString;
begin
Result := False;
// Calculate your output string here.
MyOutputStr := 'This is a sample output';
// Check if buffer is assigned, and its given length is enough
if Assigned(Buffer) and (BufferSize >= Length(MyOutputStr) + 1) then
begin
//Copy output string into buffer
StrPCopy(Buffer,MyOutputStr);
Result := True;
end;
//Return actual size of output string.
BufferSize := Length(MyOutputStr) + 1;
end;
Для версии AnsiChar вы можете использовать либо один и тот же код с AnsiString и PAnsiChar, либо преобразовать строковый параметр ANSI в Unicode и вызвать AStringFuncW внутри функции AStringFuncA, а затем преобразовать строку возврата из AStringFuncW в PAnsiChar.
2- Вот как вы можете определить эти функции в вашем блоке интерфейса для использования вашими клиентами DLL:
unit TestDLLIntf;
interface
const
TestDll = 'Test.dll';
function AStringFuncW(Buffer: PWideChar; var BufferSize: Integer): Boolean; stdcall;
function AStringFuncA(Buffer: PWideChar; var BufferSize: Integer): Boolean; stdcall;
function AStringFunc(Buffer: PWideChar; var BufferSize: Integer): Boolean; stdcall;
implementation
function AStringFuncW; external TestDll name 'AStringFuncW';
function AStringFuncA; external TestDll name 'AStringFuncA';
{$IFDEF UNICODE}
function AStringFunc; external TestDll name 'AStringFuncW';
{$ELSE}
function AStringFunc; external TestDll name 'AStringFuncA';
{$ENDIF}
end.
В приведенном выше коде функции AStringFuncW и AStringFuncA объявлены как внешние функции. Функция AStringFunc ссылается на версию WideChar в Delphi 2009 - 2010 и ссылается на версию AnsiChar в других версиях.
3- Здесь вы можете увидеть, как ваши DLL-клиенты могут использовать вашу функцию:
procedure TForm1.Button1Click(Sender: TObject);
var
Str : string;
Size : Integer;
begin
// Retrieve required buffer size
AStringFunc(nil,Size);
// Set buffer
SetLength(Str,Size);
// Retrieve output string from DLL function.
if AStringFunc(PChar(Str),Size) then
ShowMessage(Str);
end;
В приведенном выше коде клиентское приложение сначала получает фактический размер вывода из AStringFunc, затем устанавливает строковый буфер и извлекает выходную строку из DLL. Обратите внимание, что один и тот же код должен работать как в версиях Delphi для Unicode, так и для не Unicode, поскольку AStringFunc ссылается на AStringFuncA или AStringFuncW внутри вашей DLL в зависимости от того, поддерживает ли ваш компилятор Unicode или нет.