如何从 FPC DLL 接收字符串?我想发送两个指针连接它们并在 Delphi 的另一个字符串中接收结果。
library Test;
{$mode Delphi}
uses
Classes;
function Concat(const S1, S2: PWideChar): String; cdecl;
begin
Result := S1 + S2;
end;
exports
Concat name 'Concat';
begin
end.
如何从 FPC DLL 接收字符串?我想发送两个指针连接它们并在 Delphi 的另一个字符串中接收结果。
library Test;
{$mode Delphi}
uses
Classes;
function Concat(const S1, S2: PWideChar): String; cdecl;
begin
Result := S1 + S2;
end;
exports
Concat name 'Concat';
begin
end.
在 Delphi 中,String 是一种复杂的结构化类型,编译器为您管理许多细节,而 RTL 的“魔法”隐藏了这些细节。特别是,对于“长字符串”,有一个引用计数和一个长度,并且根据所涉及的 Delphi 版本,可能还有其他信息。
任何 DLL 都无法准确知道应用程序可能需要返回(或可能出现在)任何“字符串”变量(或结果)中的信息的详细信息。DLL 甚至可能根本不被 Delphi 程序调用,在这种情况下,“字符串”类型将再次完全不同。
出于这个原因,DLL 通常会选择将字符串作为指向 char类型的简单“C”样式指针来处理。也就是说,一些指向空终止内存区域的指针。DLL的调用者还必须确保相应地与 DLL 交换“字符串”值。
在某些函数返回值的情况下,问题变得复杂,因为保存结果所需的内存区域的分配必须由调用者执行,DLL 中的函数采取适当的步骤来确保内存供应就足够了。在这种情况下应用这些原则会产生一个看起来类似于此的 DLL 例程:
function Concat(const S1, S2, DEST: PWideChar; const aMaxLen: Integer): Boolean; cdecl;
begin
// left as exercise
end;
这是一个简单的实现,如果aMaxLen
足以容纳连接的结果,则返回 TRUE。您还应该考虑函数在各种条件下的其他行为(例如,S1或S2或两者都是NIL,aMaxLen太大等)。
无论为执行连接做出何种实现选择(留给您作为练习),函数调用的结果必须是将结果放在DEST指向的缓冲区中。
然后,调用者还必须确保提供了足够长度的缓冲区以及调用中指示的正确长度:
var
a, b, ab: WideString; // Or: String or UnicodeString in Delphi 2009 and later
begin
a := 'foo';
b := 'bar';
// Make sure 'ab' is big enough to hold the concatenated result of a + b
SetLength(ab, Length(a) + Length(b));
if Concat(PWideChar(a), PWideChar(b), PWideChar(ab), Length(ab)) then
// success: ab == 'foobar'
else
// something went wrong
end;
但是必须要问一个问题:当 Delphi 已经很轻松地处理字符串的连接时,为什么还要在 FPC DLL 中这样做?哦