kob*_*bik 21 delphi dll widestring
David对另一个问题的回答显示Delphi DLL函数返回一个WideString.我从没想过如果没有使用它是可能的ShareMem.
我的测试DLL:
function SomeFunction1: Widestring; stdcall;
begin
Result := 'Hello';
end;
function SomeFunction2(var OutVar: Widestring): BOOL; stdcall;
begin
OutVar := 'Hello';
Result := True;
end;
Run Code Online (Sandbox Code Playgroud)
我的来电计划:
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;
Run Code Online (Sandbox Code Playgroud)
它有效,我不明白怎么做.我所知道的约定是Windows API使用的约定,例如Windows GetClassNameW:
function GetClassNameW(hWnd: HWND; lpClassName: PWideChar; nMaxCount: Integer): Integer; stdcall;
Run Code Online (Sandbox Code Playgroud)
意味着调用者提供缓冲区和最大长度.Windows DLL以长度限制写入该缓冲区.调用者分配和释放内存.
另一种选择是DLL分配内存,例如通过使用LocalAlloc,并且调用者通过调用释放内存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!
Run Code Online (Sandbox Code Playgroud)
这是一个后续行动.
Dav*_*nan 27
A WideString与a相同BSTR,它只是Delphi的名称.内存分配由共享COM分配器处理CoTaskMemAlloc.因为所有各方都使用相同的分配器,所以您可以在一个模块中安全地分配并在另一个模块中解除分配.
因此,您不需要使用的原因是没有使用SharememDelphi堆.而是使用COM堆.这是在一个过程中的所有模块之间共享的.
如果你看一下Delphi实现WideString的,你会看到下面的API的调用:SysAllocStringLen,SysFreeString和SysReAllocStringLen.这些是系统提供的BSTRAPI函数.
您引用的许多Windows API都早于COM的发明.更重要的是,使用由调用者分配的固定长度缓冲区有性能优势.即它可以在堆栈而不是堆上分配.我也可以想象,Windows设计者不希望强制每个进程都必须链接OleAut32.dll并支付维护COM堆的代价.请记住,在设计大多数Windows API时,典型硬件的性能特征与现在大不相同.
不使用BSTR更广泛的另一个可能的原因是Windows API针对C语言.管理BSTRC语言的生命周期比C++,C#,Delphi等高级语言要复杂得多.
然而,有一个额外的复杂性.WideString返回值的Delphi ABI 与Microsoft工具不兼容.您不应该使用WideString返回类型,而是通过out参数返回它.有关更多详细信息,请参阅为什么不能将WideString用作互操作的函数返回值?
| 归档时间: |
|
| 查看次数: |
5518 次 |
| 最近记录: |