我有(遗留)VB6代码,我想从C#代码消耗。C#中使用VB6字符串数组
这有点类似于this question,但它是指从VB6传递一个数组消耗C#DLL。我的问题恰恰相反。
在VB中,有在一个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
我包裹这些2倍的DLL与tlbimp.exe是并试图调用从C#的功能。
public void UseFoo()
{
cMyImplementationClass foo;
...
var result = foo.GetErrors();
...
}
调用foo.GetErrors()引起SafeArrayRankMismatchException。我认为这表示安全数组部分here中所述的编组问题。
该建议似乎是使用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。但是,它没有在函数中指定返回值(它使用“in”引用),也不使用接口。当我运行我的代码,并从C#调用,我得到的错误没有发现
方法:“System.Array的MyDll.cImplementationClass.GetErrors()”。
这似乎是在我编辑的IL中出了什么问题,虽然我不知道从哪里出发。
我怎么能消耗从C#此功能不改变VB6代码?
- 编辑 - “msErrors”的重新定义,它初始化被返回的私有数组。
ReDim Preserve msErrors(1 To mlErrorCount)
如果我理解正确的话,在该“1”表示该阵列由1改为0索引,这是例外,我看到抛出的原因。
我明白你想要得到它第一个工作日,但是编辑IL似乎并不像一个长期的解决方案。 –
也许是这样,但它的变化编组中提到的建议的做法[这里](https://msdn.microsoft.com/en-us/library/ek1fb3c6(V = VS.100)的.aspx#cpconeditingmicrosoftintermediatelanguagemsilanchor4)。 FWIW,/ sysarray标志似乎具有相同的净效应,包括产生的错误。 – ayers
您还没有表现出你是如何声明,你从VB6代码返回数组。它是否具有等级1和下限0,即声明为“Dim msErrors(0到N)As String”之类的东西?另外,如果mbCacheErrors为false,你当前的实现似乎返回一个未初始化的数组。 – Joe