在Freepascal编译的DLL和Delphi编译的EXE之间交换字符串(PChar)

经过大量的实验,我找到了一种方法,用FreePascal编译的DLL与Delphi编译的EXE交换PChar.我负责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?

在不使用FreeString调用的情况下在DLL和Delphi应用程序之间交换字符串的一种方法是从调用应用程序中获取字符串缓冲区作为PChar,并填充DLL中的缓冲区.这就是Windows API函数在需要与调用应用程序交换字符串时的工作方式.

为此,您的调用应用程序会创建一个字符串缓冲区,并向您的DLL函数发送一个引用该缓冲区的PChar以及缓冲区大小.如果缓冲区大小小于DLL必须发送到应用程序的实际字符串,则DLL函数可以将缓冲区的实际所需大小发送到调用应用程序.

how will it behave with Delphi 2010
and the WideString by default: do I
need to force WidePChar in FreePascal
too ?

在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.

相关文章

文章浏览阅读2.2k次,点赞6次,收藏20次。在我们平时办公工作...
文章浏览阅读1k次。解决 Windows make command not found 和...
文章浏览阅读3.2k次,点赞2次,收藏6次。2、鼠标依次点击“计...
文章浏览阅读1.3w次。蓝光版属于高清版的一种。BD英文全名是...
文章浏览阅读974次,点赞7次,收藏8次。提供了更强大的功能,...
文章浏览阅读1.4w次,点赞5次,收藏22次。如果使用iterator的...