经过大量的实验,我找到了一种方法来交换PChar从FreePascal编译的DLL与 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字符串并调用FreeString方法。
这是用 Delphi EXE交换来自FreePascal DLL的字符串的最好方法吗?我可以避免从Delphi调用FreeString吗?
最后,如果这是正确的解决方案,它在 Delphi 2010和WideString的默认情况下将如何表现:我需要在FreePascal中强制使用WidePChar吗?
3条答案
按热度按时间pxy2qtax1#
在DLL和 Delphi 应用程序之间交换字符串而不使用
FreeString
调用的一种方法是从调用应用程序中获取一个字符串缓冲区作为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字符作为后缀,另一个支持AnsiChar
,其名称以A字符作为后缀。您的DLL函式宣告如下所示:
编辑:
下面是一个示例代码:
WideChar
的DLL函数如下所示:对于
AnsiChar
版本,您可以使用PAnsiChar
作为参数,或者使用AnsiString
作为变量的几乎类似的代码,或者将参数转换为PWideChar
,并在AStringFuncA
函数中调用您自己的AStringFuncW
,将其结果转换回PAnsiChar
。1.下面是如何在接口单元中定义这些函数以供DLL客户端使用:
在上面的代码中,
AStringFuncW
和AStringFuncA
函数都被声明为外部函数。AStringFunc
函数在 Delphi 2009或2010中引用WideChar
版本,而在旧版本中引用AnsiChar
。1.在这里,您可以看到DLL客户端如何使用您的函数:
在上面的代码中,客户端应用程序首先从
AStringFunc
获取实际的输出大小,然后设置一个字符串缓冲区,并从DLL中检索输出字符串。注意,相同的代码应该在Unicode和非Unicode版本的 Delphi 中都能工作,因为AStringFunc
引用了DLL中的AStringFuncA
或AStringFuncW
。这取决于您的编译器是否支持Unicode。lyfkaqu12#
根据你传递的数据,你可以使用WideString。它们被分配在Windows堆上,所以如果你在DLL中分配一个并在EXE中释放它,它们都将通过同一个内存管理器。
您应该能够使用如下所示的函数声明:
Delphi 和FreePascal都将自动处理分配和释放。WideString在支持Unicode的Delphi中和在Unicode之前的Delphi中是一样的,所以你也不需要为此做任何改变。
s8vozzvw3#
在EXE和DLL中分配/释放内存的经验法则是:分配内存的模块负责释放相同的内存。2在你的例子中,是DLL分配和释放内存,所以它是正确的。
有一个例外。 Delphi 和最新的Free Pascal版本都将WideString实现为BSTR -一种由COM使用的字符串数据类型。WideString是由Windows分配和释放的,而不是由Delphi(或Free Pascal)内存管理器分配和释放的。因此不需要使用PWideChar在EXE和DLL之间传递WideString参数-WideString可以直接传递。
更新日期:
我已经测试了以下代码:
免费Pascal(版本2.2.4)DLL:
Delphi 2009 EXE(主窗体):
过程GetAStringProc运行良好,而函数GetAStringFunc导致访问冲突。 Delphi 和Free Pascal返回字符串类型的结果似乎不同。