在EXE和DLL中分配/释放内存的经验法则是:分配内存的模块负责释放相同的内存。在您的示例中,分配和释放内存的模块是DLL,因此是正确的。
总体规则有一个例外。Delphi和最新的Free Pascal版本都将WideStrings实现为BSTR - 一种由COM使用的字符串数据类型。WideStrings由Windows分配和释放,而不是由Delphi(或Free Pascal)内存管理器。因此,在EXE和DLL之间传递WideString参数时无需使用PWideChar - 可以直接传递WideStrings。
更新:
我已测试了以下代码:
Free Pascal(版本2.2.4)DLL:
library TestLib1;
{$mode objfpc}{$H+}
{$IFDEF WINDOWS}{$R TestLib1.rc}{$ENDIF}
procedure GetAStringProc(var S: WideString); stdcall;
begin
S:= '12345';
end;
function GetAStringFunc: WideString; stdcall;
begin
Result:= '12345';
end;
exports
GetAStringProc, GetAStringFunc;
begin
end.
Delphi 2009 EXE(主窗体):
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
S: WideString;
end;
var
Form1: TForm1;
type
TGetAStringProc = procedure(var S: WideString); stdcall;
TGetAStringFunc = function: WideString; stdcall;
var
GetAStringProc: TGetAStringProc;
GetAStringFunc: TGetAStringFunc;
implementation
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
GetAStringProc(S);
Caption:= S;
S:= '';
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
S:= GetAStringFunc;
Caption:= S;
S:= '';
end;
procedure TForm1.FormCreate(Sender: TObject);
var
LibHandle: THandle;
begin
LibHandle:= LoadLibrary('TestLib1.dll');
if LibHandle <> 0 then begin
@GetAStringProc:= GetProcAddress(LibHandle, 'GetAStringProc');
@GetAStringFunc:= GetProcAddress(LibHandle, 'GetAStringFunc');
end;
if not Assigned(GetAStringProc) or not Assigned(GetAStringFunc) then
ShowMessage('Error!');
end;
end.
看起来获取字符串的过程(GetAStringProc)能够正常工作,而获取字符串的函数(GetAStringFunc)会导致访问冲突。Delphi和Free Pascal似乎以不同的方式返回字符串类型的结果。