如何通过InvokeHelper将variant *传递给C#?

时间:2018-10-17 04:21:33

标签: c# c++ com variant dispatch

我有一个遗留的c ++组件,它使用了性质相似的ATL控件,程序ID输入到该组件。它使用progid创建ATL对象,并使用dispatchid通过InvokeHelper从ATL控件调用方法,如下所示,

DISPID methodDispID;  // dispatchid

long lValue = 0; // first argument long
short nIdx = 1   // second argument short
VARIANT varValue;     // third argument variant

long returnCode = 0;  // return code long

static BYTE parms[] = VTS_I4 VTS_I2 VTS_PVARIANT;

InvokeHelper(methodDispID, DISPATCH_METHOD, VT_ERROR, (void*)&returnCode, parms, &varValue, lValue, nIdx);

在C ++ ActiveX方法中,如下所示,

[id(1), helpstring("method GetValue")] long GetValue(long lValue, short nIdx,VARIANT *varValue);

现在,我尝试在C#中引入Active X,这意味着我有一个Usercontrol,我将此C#usercontrol的progid提供给了遗留组件,它创建了C#usercontrol的对象,并尝试调用C#Usercontrol的GeValue方法,在下面定义,

C#

interface IMyInterface
{
         [DispId(1)] Int32 GetValue(System.Int32 lOrder, System.Int16 
             nIdx,object varval); 
}

class MyClass : IMyInterface
{
      System.Int32 GetValue(System.Int32 lValue, System.Int16 nIdx,
                                    ref object vCBValue)
      {

      }
}

该调用即将到达C#用户控件的GetValue方法,但会引发异常

  

System.Runtime.InteropServices.COMException   在   System.RuntimeType.ForwardCallToInvokeMember(System.String,   System.Reflection.BindingFlags,System.Object,Int32 [],   System.Runtime.Remoting.Proxies.MessageData ByRef)

我尝试如下更改C#方法定义,但无济于事,

System.Int32 GetValue(System.Int32 lValue, System.Int16 nIdx,
                    [MarshalAs(UnmanagedType.Struct)]  ref object varValue);

System.Int32 GetValue(System.Int32 lValue, System.Int16 nIdx,
                     ref IntPtr varValue);

如何通过InvokeHelper将variant *传递给C#?

注意:对于C ++和C#用户控件,使用InvokeHelper调用该方法的组件代码应该相同

1 个答案:

答案 0 :(得分:0)

如果您想重现c ++ COM代码:

[id(1), helpstring("method GetValue")] 
long GetValue(long lValue, short nIdx,VARIANT *varValue);

...改为c#,然后代替

System.Int32 GetValue(System.Int32 lValue, System.Int16 nIdx, ref object vCBValue);

...应该是:

object GetValue(System.Int32 lValue, System.Int16 nIdx);

那是因为所有c ++ COM方法都返回一个HRESULT(在您的情况下为long),其他任何返回值都是通过out参数来实现的。

在.NET中,无需定义HRESULT,我们可以显式返回值,而不必使用out