本文介绍了在C#中使用VB6字符串数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我有(旧)VB6代码,我想从C#代码中使用。I have (legacy) VB6 code that I want to consume from C# code.这有点类似于这个问题,但它指的是从VB6传递一个占用C#dll的数组。我的问题正好相反。This is somewhat similar to this question, but it refers to passing an array from VB6 consuming a C# dll. My problem is the opposite.在VB中,一个dll中有一个接口,而在另一个dll中有一个实现。In VB, there is an interface in one dll, and an implementation in another.接口:[ 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中的实现(片段):Implementation (fragment) in cMyImplementationClass:Private Function IMyInterface_GetErrors() As String() If mbCacheErrors Then IMyInterface_GetErrors = msErrors End IfEnd Function我用tlbimp.exe包装了这两个dll,并尝试从C#调用该函数。I wrapped these 2 dlls with tlbimp.exe and attempt to call the function from C#.public void UseFoo(){ cMyImplementationClass foo; ... var result = foo.GetErrors(); ...}调用foo.GetErrors()会导致 SafeArrayRankMismatchException 。我认为这表明安全阵列部分中所述的编组问题这里。Calling foo.GetErrors() causes a SafeArrayRankMismatchException. I think this indicates a marshaling problem as described in the Safe Arrays section here.建议似乎是使用tlbimp.exe的/ sysarray参数或手动编辑生成的IL,我尝试过。The recommendation seems to be to use the /sysarray parameter of tlbimp.exe or to manually edit the IL produced, which I tried.原始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我在接口和实现上都进行了相同的功能签名更改。 此处 。但是,它没有在函数中指定返回值(它使用 in引用),也没有使用接口。当我运行代码并从C#调用时,出现错误I made identical function signature changes in both the interface and implementation. This process is described here. However, it doesn't specify a return value in the function (it uses an "in" reference) and also doesn't use an interface. When I run my code and call from C#, I get the error 找不到方法:'System.Array MyDll.cImplementationClass.GetErrors( )'。 Method not found: 'System.Array MyDll.cImplementationClass.GetErrors()'.似乎我编辑的IL中出了点问题,尽管我不知道要去哪里从这里开始。It seems to be that something is wrong in the IL that I edited, though I don't know where to go from here.如何在不更改VB6代码的情况下从C#使用此功能?How can I consume this function from C# without changing the VB6 code?-编辑-重新定义 msErrors,从而初始化要返回的私有数组。--Edit--Redefinition of "msErrors", which initializes the private array that gets returned.ReDim Preserve msErrors(1 To mlErrorCount)如果我理解正确,则 1表示该数组是从1而不是0,这是引发异常的原因。If I understand correctly, the "1" in that means that the array is indexed from 1 instead of 0, which is the cause of the exception I see get thrown.推荐答案我按照您的所有步骤进行操作,除了使用TlbImp.exe。相反,我直接将DLL添加到C#项目参考中。这样做,我得到IL,它是您提供的两个样本之间的交叉:I followed all your steps, except using TlbImp.exe. Instead, I directly added the DLLs into the C# project reference. Doing this, I get IL which is a cross between both of the samples you give:.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也没有内在地支持该语言。I have done the same code as you, and essentially you are assigning to a variable of type Array. Whilst the CLR supports arrays with lower bounds other than 0, AFAIK, no language, even VB.NET, supports it instrinsically in the language.我的测试代码变为: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]); 这篇关于在C#中使用VB6字符串数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
07-22 20:43
查看更多