delphi – 为什么WideString不能用作interop的函数返回值?
我有不止一次,建议人们使用WideString类型的返回值用于互操作。
> Accessing Delphi DLL throwing ocasional exception 这个想法是WideString与 但是,似乎WideString不能用作interop的函数返回值。 考虑下面的Delphi DLL。 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; begin end. 和以下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 = (OutParam) GetProcAddress(lib,"TestWideStringOutParam"); BSTR str = TestBSTR(); wprintf(L"%sn",str); SysFreeString(str); str = NULL; TestWideStringOutParam(str); wprintf(L"%sn",str); SysFreeString(str); str = NULL; str = TestWideString();//fails here wprintf(L"%sn",str); SysFreeString(str); 调用TestWideString失败,出现此错误:
类似地,如果我们尝试从C#用p / invoke调用它,我们有一个失败: [DllImport(@"pathtomydll")] [return: MarshalAs(UnmanagedType.BStr)] static extern string TestWideString(); 错误是:
通过p / invoke调用TestWideString按预期工作。 因此,使用传递引用与WideString参数和映射到BSTR似乎工作完美。但不能用于函数返回值。我已经测试了这个Delphi 5,2010和XE2,并观察相同的行为在所有版本。 执行进入Delphi并几乎立即失败。对Result的赋值变成对System._WStrAsg的调用,第一行读为: CMP [EAX],EDX 现在,EAX是$ 00000000,自然有一个访问冲突。 任何人都可以解释这个?我做错了什么?我不合理的期望WideString函数值是可行的BSTRs?还是只是一个Delphi缺陷? 解决方法
在常规Delphi函数中,函数return实际上是通过引用传递的参数,即使在语法上它看起来像一个“out”参数。你可以这样测试(这可能是版本相关的):
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() 您的代码失败,因为Delphi和C之间的不匹配的调用约定相对于函数结果的传递机制的理解。在C中,函数返回的行为类似于语法建议:out参数。但对于Delphi它是一个var参数。 要解决这个问题,请尝试: function TestWideString: WideString; stdcall; begin Pointer(Result) := nil; Result := 'TestWideString'; end; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |