David 对另一个问题的回答显示了一个返回 WideString 的 Delphi DLL 函数。我从没想过不使用ShareMem
.
我的测试DLL:
function SomeFunction1: Widestring; stdcall;
begin
Result := 'Hello';
end;
function SomeFunction2(var OutVar: Widestring): BOOL; stdcall;
begin
OutVar := 'Hello';
Result := True;
end;
我的来电程序:
function SomeFunction1: WideString; stdcall; external 'Test.dll';
function SomeFunction2(var OutVar: Widestring): BOOL; stdcall; external 'Test.dll';
procedure TForm1.Button1Click(Sender: TObject);
var
W: WideString;
begin
ShowMessage(SomeFunction1);
SomeFunction2(W);
ShowMessage(W);
end;
它有效,我不明白如何。我知道的约定是 Windows API 使用的约定,例如 Windows GetClassNameW
:
function GetClassNameW(hWnd: HWND; lpClassName: PWideChar; nMaxCount: Integer): Integer; stdcall;
这意味着调用者提供缓冲区和最大长度。Windows DLL 以长度限制写入该缓冲区。调用者分配和释放内存。
另一种选择是 DLL 例如通过 usingLocalAlloc
分配内存,而调用者通过调用LocalFree
.
内存分配和释放如何与我的 DLL 示例一起使用?是否因为结果是WideString
(BSTR
)而发生“魔术”?为什么不使用如此方便的约定声明 Windows API?(是否有任何已知的使用这种约定的 Win32 API?)
编辑:
我用 C# 测试了 DLL。
调用SomeFunction1
会导致 AV ( Attempted to read or write protected memory
)。
SomeFunction2
工作正常。
[DllImport(@"Test.dll")]
[return: MarshalAs(UnmanagedType.BStr)]
static extern string SomeFunction1();
[DllImport(@"Test.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SomeFunction2([MarshalAs(UnmanagedType.BStr)] out string res);
...
string s;
SomeFunction2(out s);
MessageBox.Show(s); // works ok
MessageBox.Show(SomeFunction1()); // fails with AV!
这是后续行动。