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函数发送一个引用该缓冲区的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.