我有(旧的)VB6 代码,我想从 C# 代码中使用它。
这有点类似于这个问题 https://stackoverflow.com/questions/23507416/passing-string-array-from-vb6-to-c-net,但它指的是从使用 C# dll 的 VB6 传递数组。我的问题恰恰相反。
在VB中,一个dll中有一个接口,另一个dll中有一个实现。
界面:
[
odl,
uuid(339D3BCB-A11F-4fba-B492-FEBDBC540D6F),
version(1.0),
dual,
nonextensible,
oleautomation,
helpstring("Extended Post Interface.")
]
interface IMyInterface : IDispatch {
[id(...),helpstring("String array of errors.")]
HRESULT GetErrors([out, retval] SAFEARRAY(BSTR)* );
};
cMyImplementationClass 中的实现(片段):
Private Function IMyInterface_GetErrors() As String()
If mbCacheErrors Then
IMyInterface_GetErrors = msErrors
End If
End Function
我用 tlbimp.exe 包装了这 2 个 dll,并尝试从 C# 调用该函数。
public void UseFoo()
{
cMyImplementationClass foo;
...
var result = foo.GetErrors();
...
}
调用 foo.GetErrors() 会导致SafeArrayRankMismatchException https://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safearrayrankmismatchexception(v=vs.110).aspx。我认为这表明存在安全数组部分所述的编组问题here https://msdn.microsoft.com/en-us/library/z6cfh6e6(v=vs.110).aspx#cpcondefaultmarshalingforarraysanchor3.
建议似乎是使用 tlbimp.exe 的 /sysarray 参数或手动编辑生成的 IL,我尝试过。
原来的IL是这样的:
.method public hidebysig newslot virtual
instance string[]
marshal( safearray bstr)
GetErrors() runtime managed internalcall
{
.override [My.Interfaces]My.Interface.IMyInterface::GetErrors
} // end of method cImplementationClass::GetErrors
而更新后的版本是:
.method public hidebysig newslot virtual
instance class [mscorlib]System.Array
marshal( safearray)
GetErrors() runtime managed internalcall
{
.override [My.Interfaces]My.Interface.IMyInterface::GetErrors
} // end of method cImplementationClass::GetErrors
我在接口和实现中进行了相同的函数签名更改。描述了这个过程here https://msdn.microsoft.com/en-us/library/ek1fb3c6(v=vs.100).aspx#cpconeditingmicrosoftintermediatelanguagemsilanchor4。但是,它没有在函数中指定返回值(它使用“in”引用),也不使用接口。当我运行代码并从 C# 调用时,出现错误
找不到方法:“System.Array MyDll.cImplementationClass.GetErrors()”。
我编辑的 IL 似乎有问题,但我不知道从哪里开始。
如何在不更改 VB6 代码的情况下从 C# 使用此函数?
- 编辑 -
重新定义“msErrors”,初始化返回的私有数组。
ReDim Preserve msErrors(1 To mlErrorCount)
如果我理解正确的话,其中的“1”意味着数组从 1 而不是 0 索引,这是我看到抛出异常的原因。