-1

I have a legacy c++ component.It consumes ATL Controls of similar nature.Prog ID is input to this component. It uses the progid to create ATL object and it uses dispatchid to call methods from ATL control using InvokeHelper as below,

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);

In C++ ActiveX method looks below,

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

Now I am trying to introduce Active X in C#, means I have a Usercontrol, I am giving this C# usercontrol's progid to the legacy component, It creates the object of C# usercontrol and tries to call the GeValue method of C# Usercontrol which is defined below,

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)
      {

      }
}

The call is coming to GetValue method of C# usercontrol, but it's throwing the exception

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

I tried to change C# method definitions as below, but nothing worked,

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);

How to pass variant* to C# through InvokeHelper ?

Note: The component code to call the method using InvokeHelper should be same for both C++ and C# usercontrols

srajeshnkl
  • 883
  • 3
  • 16
  • 49

1 Answers1

0

If you are trying to reproduce the c++ COM code:

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

...to c#, then instead of

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

...it should be:

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

That's because all c++ COM methods return a HRESULT (the long in your case), any other return values are via out arguments.

In .NET, there is no need to define the HRESULT and we can return values explicitly rather than use an out

  • After making this change also, the same exception is thrown, and also I have one more method [id(2), helpstring("method SetValue")] long SetValue(VARIANT* Var,VARIANT* bstrVal,long lOrder,short nIdx); How to make it in C# ? – srajeshnkl Oct 17 '18 at 05:14
  • 1
    @RajeshSubramanian are you specifying the progids in c# too? Normally you would do so on an interface –  Oct 17 '18 at 05:27
  • @@MickyD yes I am setting DispID like this in interface methods, [DispId(1)] Int32 GetValue(System.Int32 lOrder, System.Int16 nIdx,object varval); – srajeshnkl Oct 17 '18 at 05:41
  • @RajeshSubramanian I think you could probably put this into a new question. It sounds as though you have larger problems exporting a c# class to COM –  Oct 17 '18 at 07:16