void SumOfArray::GetSum(VARIANT FAR* array, double FAR* sumresult) 
1。不要使用array作为参数名字,包括在你的IDL (ODL)中都不要用。如果使用array作为参数,我使用ILDASM察看了一下tlbimp生成的DLL,发现GetSum()的marshal代码不对--marshal (struct)'array'. 选择变量名称时候要小心,不要使用保留keywords。2。我把你的代码放到ATL中简单测试了一下,还有一个错误:
SafeArrayGetElement(array->parray, &i, &vinput[i]);
---〉
SafeArrayGetElement(pArray->parray, &i, &vinput[i].dblVal);根据我的建议,你看看问题是否解决了?- 微软全球技术中心 VC技术支持 本贴子以“现状”提供且没有任何担保,同时也没有授予任何权利。具体事项可参见使用条款 
(http://support.microsoft.com/directory/worldwide/zh-cn/community/terms_chs.asp)。 
为了为您创建更好的讨论环境,请参加我们的用户满意度调查 
(http://support.microsoft.com/directory/worldwide/zh-cn/community/survey.asp?key=(S,49854782))。

解决方案 »

  1.   

    acptvc(微软全球技术中心 VC技术支持):
    你好!
    按照您的要求做了,但错误依旧!
    我感觉是不是C#里的Boxing操作有问题?
    对于COM接口函数上变体类型的参数(特别是Variant SafeArray),C#里究竟应该怎样调用并进行传递???
      

  2.   

    我试了一下,你原先C++的代码可以work。
    下面试我的C#源代码,测试通过:
    using System;
    using System.Runtime.InteropServices;
    using SUMTESTLib;namespace QQChen79.LearnCSharp.Interop {
    public class SumTest {
    public static void Main() {
    SumClass sum = new SumClass();
    object[] mydbl = new object[5] {0.1, 0.2, 0.3, 0.4, 0.5};
    double res = 0;
    object o = mydbl;
    sum.GetSum(ref o, ref res);
    Console.WriteLine(res);
    }
    }
    }--> SafeArrayGetElement(array->parray, &i, &vinput[i]);
    这一句假设SafeArray里面的元素是VARIANT,而不是直接存储double。
    --> SafeArrayGetElement(pArray->parray, &i, &vinput[i].dblVal);
    这一句假设SafeArray里面的元素是直接存储double的。所以,在C#这边,如果声明的数组类型是double[],那么Marshal的结果就是一个直接存储double的SAFEARRAY,所以出错。如果C#声明一个object[],那么Marshal的结果是一个包含VARIANT的SAFEARRAY,也就是你的例子里面真正需要的。
      

  3.   

    qqchen79(知秋一叶):
       您好!
       我试了一下您的代码,但错误依旧。
       不过我感觉您说的很有道理,能把您的源码(c++&c#)发给我吗?
       我的:[email protected]
      

  4.   

    一句话就将你问题彻底解决了,而且以后永远不会再烦恼,能不能
    多给我点分!?嘿嘿!
    既然您会用VB6,干嘛不用VB6做个COM类将Variant数组转变成非Variant数组???因为.Net中调用VB6开发的COM组件特别稳定!!!
      

  5.   

    qqchen79(知秋一叶),你好!!!
    非常感谢你的帮助!你是高手,你发过来的代码确实解决了问题,为你加分!
    但是现在我有一个非常大的疑惑,烦请你给予关注。
    ——你的代码能解决问题,而我的不行。经仔细比较,说明如下——
    1、你是用ATL做的COM组件,我是用MFC做的自动化对象(.dll)。
    2、你的接口函数似乎是这样定义的-
    STDMETHODIMP CSum::GetSum(VARIANT *array, double *sumresult){……}
    我的是这样的-
    void SumOfArray::GetSum(VARIANT FAR* array, double FAR* sumresult){……}
    请注意FAR字眼,这是添加自动化方法时自动加上的,但FAR字眼在.odl文件里不可见。
    3、你我的组件在VB6及VC6里调用都是成功的,方法同问题中给出的。
    4、C#里,调用你的组件OK,我的则总是出现这样的错误提示-
    System.Runtime.InteropServices.COMException (0x80020005): 类型不匹配。
    但你我的组件在.Net对象浏览器中查看其接口函数的信息是一致的,如下-
    GetSum(ref object,ref double),具体的-
    public virtual void GetSum(System.Object array, System.Double sumresult)
    5、我左思右想都化解不了这团迷雾,请原谅我水平有限(我是在校学生,C++、COM & C#完全自学),ATL做COM我不熟(得好好学)。就表面上的东西看,我不清楚你我代码的差别在哪,请你指点分析!
    6、COM接口函数的参数往往含有比较复杂的变体数组(比如说包含不同数据类型,当然有解包程序),这种情况在C#中调用应如何处理,请指教!
    7、任何建议或实例源码,请发至[email protected],再次感谢高手的帮助!!!
      

  6.   

    好像看不出什么问题,把代码发给我吧。
    email: [email protected]