加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

在C#中使用VB6字符串数组

发布时间:2020-12-15 06:29:07 所属栏目:百科 来源:网络整理
导读:我有(遗产)VB6代码,我想从C#代码消费. 这有点类似于this question,但它指的是从VB6传递一个消耗C#dll的数组.我的问题是相反的. 在VB中,在一个dll中有一个接口,另一个是一个实现. 接口: [ odl,uuid(339D3BCB-A11F-4fba-B492-FEBDBC540D6F),version(1.0),dual
我有(遗产)VB6代码,我想从C#代码消费.

这有点类似于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中的实现(fragment):

Private Function IMyInterface_GetErrors() As String()

    If mbCacheErrors Then
        IMyInterface_GetErrors = msErrors
    End If

End Function

我用tlbimp.exe包装了这两个dll,并尝试从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#调用时,我得到错误

Method not found: ‘System.Array MyDll.cImplementationClass.GetErrors()’.

似乎在编辑的IL中有些错误,尽管我不知道从这里去哪里.

如何在不改变VB6代码的情况下从C#消费这个函数?

– 编辑 –
重新定义“msErrors”,它初始化返回的私有数组.

ReDim Preserve msErrors(1 To mlErrorCount)

如果我理解正确,那么“1”就意味着数组从1而不是0被索引,这是我看到的异常的原因.

解决方法

我遵循所有的步骤,除了使用TlbImp.exe.相反,我直接将DLL添加到C#项目引用中.做到这一点,我得到的IL是两个样品之间的交叉:
.method public hidebysig newslot abstract virtual 
        instance class [mscorlib]System.Array 
        marshal( safearray bstr) 
        GetErrors() runtime managed internalcall
{
  .custom instance void [mscorlib]System.Runtime.InteropServices.DispIdAttribute::.ctor(int32) = ( 01 00 00 00 03 60 00 00 )                         // .....`..
} // end of method _IMyInterface::GetErrors

我已经做了和你一样的代码,并且基本上你分配给一个类型为Array的变量.虽然CLR支持除0以外的下限的数组,但是AFAIK,没有任何语言,甚至是VB.NET,它在语言中支持它.

我的测试代码变成:

cMyImplementationClass myImpClass = new cMyImplementationClass();
IMyInterface myInterface = myImpClass as IMyInterface;

myImpClass.CacheErrors = true;

// Retrieve the error strings into the Array variable.
Array test = myInterface.GetErrors();

// You can access elements using the GetValue() method,which honours the array's original bounds.
MessageBox.Show(test.GetValue(1) as string);

// Alternatively,if you want to treat this like a standard 1D C# array,you will first have to copy this into a string[].
string[] testCopy = new string[test.GetLength(0)];
test.CopyTo(testCopy,0);
MessageBox.Show(testCopy[0]);

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读