为什么不能将WideString用作互操作的函数返回值?我不止一次建议人们使用类型的返回值。WideString为了互操作的目的。访问DelphiDLL抛出ocasional异常ASP.NET Web应用程序在IIS Web服务器上调用DelphiDLL,返回Pchar字符串时锁定为什么DelphiDLL可以在不使用ShareMem的情况下使用WideString?我的想法是WideString与BSTR..因为BSTR在共享COM堆上分配,那么在一个模块中分配并在另一个模块中释放是没有问题的。这是因为所有各方都同意使用相同的堆,COM堆。然而,似乎WideString不能用作互操作的函数返回值。考虑下面的DelphiDLL。library WideStringTest;uses
ActiveX;function TestWideString: WideString; stdcall;begin
Result := 'TestWideString';end;function TestBSTR: TBstr; stdcall;begin
Result := SysAllocString('TestBSTR');end;procedure TestWideStringOutParam(out str: WideString); stdcall;begin
str := 'TestWideStringOutParam';end;exports
TestWideString, TestBSTR, TestWideStringOutParam;beginend.以及下面的C+代码:typedef BSTR (__stdcall *Func)();typedef void (__stdcall *OutParam)(BSTR &pstr);HMODULE lib = LoadLibrary(DLLNAME);Func TestWideString =
(Func) GetProcAddress(lib, "TestWideString");Func TestBSTR = (Func) GetProcAddress(lib, "TestBSTR");OutParam TestWideStringOutParam = (Out
Param) GetProcAddress(lib,
"TestWideStringOutParam");BSTR str = TestBSTR();wprintf(L"%s\n", str);SysFreeString(str);str = NULL;TestWideSt
ringOutParam(str);wprintf(L"%s\n", str);SysFreeString(str);str = NULL;str = TestWideString();
//fails herewprintf(L"%s\n", str);SysFreeString(str);打电话给TestWideString此错误失败:BSTRtest.exe中0x772015de处的未处理异常:0xC0000005:访问冲突读取位置0x00000000。类似地,如果我们尝试用p/Invoke从C#调用它,则会有一个失败:[DllImport(@"path\to\my\dll")][return: MarshalAs(UnmanagedType.BStr)]static extern string TestWideString();错误是:ConsoleApplication10.exe中发生了“System.Runtime.InteropServices.SEHException”类型的未处理异常附加信息:外部组件引发异常。呼叫TestWideStringVia/Invoke按预期工作。因此,使用WideString参数按引用传递,并将它们映射到BSTR似乎运作得很好。但不适用于函数返回值。我已经在Delphi 5,2010和XE2上测试了这一点,并且在所有版本上都观察到了相同的行为。执行进入Delphi,几乎立即失败。分配给Result变成打电话到System._WStrAsg,第一行内容如下:CMP [EAX],EDX现在,EAX是$00000000当然会有访问违规行为。有人能解释一下吗?我做错什么了吗?我的期望是不是不合理?WideString函数值是可行的BSTR是吗?还是仅仅是德尔菲的缺陷?
3 回答
白衣非少年
TA贡献1155条经验 获得超0个赞
function DoNothing: IInterface;begin if Assigned(Result) then ShowMessage('result assigned before invocation') else ShowMessage('result NOT assigned before invocation');end;procedure TestParameterPassingMechanismOfFunctions;var X: IInterface;begin X := TInterfaceObject.Create; X := DoNothing; end;
TestParameterPassingMechanismOfFunctions()
out
var
function TestWideString: WideString; stdcall;begin Pointer(Result) := nil; Result := 'TestWideString';end;
- 3 回答
- 0 关注
- 426 浏览
添加回答
举报
0/150
提交
取消