在不使用 FreeString 调用的情况下在 DLL 和 Delphi 应用程序之间交换字符串的一种方法是从调用应用程序中获取字符串缓冲区作为 PChar,并将缓冲区填充到 DLL 中。这就是 Windows API 函数在需要与调用应用程序交换字符串时的工作方式。
为此,您的调用应用程序创建一个字符串缓冲区,并将引用该缓冲区的 PChar 连同缓冲区大小一起发送到您的 DLL 函数。如果缓冲区大小小于 DLL 必须发送给应用程序的实际字符串,则您的 DLL 函数可以将缓冲区实际所需的大小发送给调用应用程序。
默认情况下,Delphi 2010 和 WideString 将如何表现:我是否也需要在 FreePascal 中强制 WidePChar ?
在 Delphi 2009 和 Delphi 2010 中,PChar 等于 PWideChar。在以前的 Delphi 版本中,据我所知,在 FreePascal 中,PChar 等于 PAnsiChar。因此,如果您从 DLL 返回 PChar,您的代码将无法在 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;
编辑:
这是一个示例代码:
1-您的 Widechar DLL 函数将是这样的:
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,并在 AStringFuncA 函数中调用 AStringFuncW,然后将返回字符串从 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 函数在 Delphi 2009 - 2010 中参考 WideChar 版本,在其他版本中参考 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 中检索输出字符串。请注意,相同的代码应该适用于 Unicode 和非 Unicode 版本的 Delphi,因为 AStringFunc 在您的 DLL 中引用 AStringFuncA 或 AStringFuncW,具体取决于您的编译器是否支持 Unicode。