经过大量实验,我找到了一种将 FreePascal 编译的 DLL 中的 PChar 与 Delphi 编译的 EXE 交换的方法。我负责 DLL 和 EXE 源代码,但其中一个必须在 FreePascal 中,另一个在 Delphi 中。我的解决方案涉及DLL中的以下方法:
function GetAString(): PChar;
var aString: string;
begin
aString := 'My String';
result := StrAlloc(length(aString) + 1);
StrPCopy(result, aString);
end;
procedure FreeString(aString: PChar);
begin
StrDispose(aString);
end;
从 Delphi EXE 中,要调用 GetAString 方法,我需要调用 GetAString 方法,将 PChar 保存到实际的 Delphi String 并调用 FreeString 方法。
这是从 FreePascal DLL 与 Delphi EXE 交换字符串的最佳方法吗?我可以避免从 Delphi 调用 FreeString 吗?
最后,如果这是正确的解决方案,默认情况下它在 Delphi 2010 和 WideString 中的表现如何:我是否也需要在 FreePascal 中强制使用 WidePChar?
一种在 DLL 和 Delphi 应用程序之间交换字符串而不使用FreeString
调用是从调用应用程序获取字符串缓冲区作为PChar
,并填充DLL中的缓冲区。这就是 Windows API 函数需要与调用应用程序交换字符串时的工作方式。
为此,您的调用应用程序创建一个字符串缓冲区,并发送一个PChar
将该缓冲区以及缓冲区大小引用到您的 DLL 函数。如果缓冲区大小小于 DLL 必须发送到应用程序的实际字符串,则 DLL 函数可以将缓冲区实际所需的大小发送到调用应用程序。
默认情况下,它在 Delphi 2010 和 WideString 中的表现如何:我也需要在 FreePascal 中强制使用 WidePChar 吗?
在德尔福 2009 和德尔福 2010 中,PChar
等于PWideChar
。在以前版本的 Delphi 中,据我所知,在 FreePascal 中,PChar
等于PAnsiChar
。所以如果你回来PChar
从您的 DLL 中,您的代码将无法在 Delphi 2010 中正常工作。您应该明确使用PAnsiChar
or PWideChar
。您可以再次遵循 Windows API 函数的模式:它们几乎为每个 API 函数提供两个版本 - 一个带有WideChar
支持谁的名字有W字符作为后缀,另一个带有AnsiChar
支持其名字带有A字符作为后缀。
你的 DLL 函数声明将是这样的:
function AStringFuncW(Buffer: PWideChar; var BufferSize: Integer): Boolean;
function AStringFuncA(Buffer: PAnsiChar; var BufferSize: Integer): Boolean;
EDIT:
这是示例代码:
-
您的 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;
For the AnsiChar
您使用的版本PAnsiChar
作为参数和几乎相似的代码AnsiString
作为变量,或者将参数转换为PWideChar
并调用你自己的AStringFuncW
在你的里面AStringFuncA
函数,您将其结果转换回PAnsiChar
.
-
以下是如何在接口单元中定义这些函数以供 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
and AStringFuncA
函数被声明为外部函数。这AStringFunc
函数是指WideChar
Delphi 2009 或 2010 中的版本,以及AnsiChar
在旧版本中。
-
在这里您可以看到 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
or AStringFuncW
在您的 DLL 中,具体取决于您的编译器是否支持 Unicode。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)