如何从FPC DLL接收字符串?

时间:2014-12-07 18:16:55

标签: delphi fpc delphi-xe7

如何从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.

1 个答案:

答案 0 :(得分:3)

在Delphi中,String是一个复杂的结构化类型,编译器为您管理了许多细节,并隐藏了这些细节的RTL“魔法”。特别是,对于“长字符串”,有一个引用计数和一个长度,并且根据所涉及的Delphi版本,可能还有其他信息。

任何DLL都无法准确知道应用程序可能需要返回(或可能存在)任何“字符串”变量(或结果)的信息的详细信息。根本不可能通过Delphi程序调用DLL,在这种情况下,'string'类型将再次完全不同。

出于这个原因,DLL通常会选择将字符串作为简单的'C'样式指向char 类型的指针来处理。也就是说,一些指向空终止的内存区域的指针。然后,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中执行此操作? O.o