1

I have an ActiveX DLL which I try to use in my C# application. Most interop methods work. I am having problems with the following method (the unmanaged definition):

HRESULT SendData([in] long lChID, [in] short nIndex, 
    [in] VARIANT vData, [out, retval] VARIANT_BOOL *bResult);

The VARIANT data type is unusual for me and I do not know what to do with it as COM and marshalling is a new topic for me.

BOOL CControl::SendData(long lChID, short nIndex, const VARIANT& vData)
{
    BOOL result;
    static BYTE parms[] = VTS_I4 VTS_I2 VTS_VARIANT;

    InvokeHelper(0x1f, DISPATCH_METHOD, VT_BOOL,
        (void*)&result, parms, lChID, nIndex, &vData);

    return result;
}

I used the .NET tool AxImp.exe to get the managed wrapper for the method:

[DispId(31)]
[MethodImpl(MethodImplOptions.InternalCall,
    MethodCodeType = MethodCodeType.Runtime)]
public virtual bool SendData([In] int lChID, [In] short nIndex, 
    [MarshalAs(UnmanagedType.Struct), In] object vData);

Is the C# method wrapper correctly generated?

What would be the correct way to initialize and populate the vData parameter?

EDIT:

Some more code example to help decipher the 3rd parameter VARIANT.

VARIANT var;
VariantInit(&var);

var.vt = VT_UI1 | VT_BYREF;
var.pbVal = (unsigned char *)pSend;

if (!m_Control.SendData(m_lCurChID, m_combo.GetCurSel() + 1, var))
    AfxMessageBox(_T("SendData failed"));

The var.vt and var.pbVal are not known to me. Is there any corresponding code in C#?

J Pollack
  • 2,788
  • 3
  • 29
  • 43
  • if you are not sure of the type since C# doesn't have a Variant type you can try something like this Object xyz=MyThirdPartyLib.MyThirdPartyLibFunction(); type t = typeof(xyz); todetermine the type to use in reference to the Variant.. replace the MyThirdPartyLib.MyThirdPartyLibFunction with your method / function .. – MethodMan Feb 06 '12 at 17:46
  • If you don't know what kind of data type should be passed then we won't have a shot at it either. Find more sample code that uses this or ask for help from the vendor or author. – Hans Passant Feb 06 '12 at 19:57
  • Thank you for the comments. I have learned that the C++ VARIANT does not have one-to-one definition in C#. I have added an example code to the question. Does it have all the valuable information to write corresponding C# code for it? Thanks – J Pollack Feb 07 '12 at 09:47

1 Answers1

1

Check out the System.Runtime.InteropServices.Marshal.GetNativeVariantForObject() method. Assuming you know what the actual content of vData is supposed to be, you should be able to define the interop signature with IntPtr, and pass the result of that method in.

Your signature should thus be something like this:

public virtual bool SendData(
    [In] int lChID, 
    [In] short nIndex, 
    [MarshalAs(UnmanagedType.Struct), In] IntPtr vData);

while the calling code would be:

MyClass vData = ...;// build the actual data. 
IntPtr variantPtr = Marshal.AllocHGlobal(Marshal.SizeOf(vData ) + ???); // Allocate the space. I'm not entirely sure how much space you need here in addition to the base object size.
Marshal.GetNativeVariantForObject(vData , variantPtr); //fills the allocated memory with the VARIANT.

Going over it now, it seems there are some question marks. This is why the best course of action is often to let the default marshaller do its job. If your vData is a byte[], simply define the interop function with byte[] and see what happens.

Avner Shahar-Kashtan
  • 14,492
  • 3
  • 37
  • 63
  • Should it just work if I pass byte array? As I know very little or actually nothing about the marshalling, could you give an example how to define the interop signature with the IntPtr? – J Pollack Feb 07 '12 at 13:55