C# 从C调用变量参数类型为的托管API方法#

C# 从C调用变量参数类型为的托管API方法#,c#,marshalling,com-interop,C#,Marshalling,Com Interop,我有一个ActiveX DLL,我试图在我的C#应用程序中使用它。大多数互操作方法都有效。我对以下方法(非托管定义)有问题: 变量数据类型对我来说是不寻常的,我不知道如何处理它,因为COM和编组对我来说是一个新的主题 BOOL CControl::SendData(long lChID, short nIndex, const VARIANT& vData) { BOOL result; static BYTE parms[] = VTS_I4 VTS_I2 VTS_VA

我有一个ActiveX DLL,我试图在我的C#应用程序中使用它。大多数互操作方法都有效。我对以下方法(非托管定义)有问题:

变量数据类型对我来说是不寻常的,我不知道如何处理它,因为COM和编组对我来说是一个新的主题

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;
}
我使用.NET工具AxImp.exe获取该方法的托管包装器:

[DispId(31)]
[MethodImpl(MethodImplOptions.InternalCall,
    MethodCodeType = MethodCodeType.Runtime)]
public virtual bool SendData([In] int lChID, [In] short nIndex, 
    [MarshalAs(UnmanagedType.Struct), In] object vData);
C#方法包装器是否正确生成

初始化和填充vData参数的正确方法是什么

编辑:

更多的代码示例有助于破译第三个参数变量

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"));
我不知道var.vt和var.pbVal。C#中是否有相应的代码?

签出。假设您知道vData的实际内容应该是什么,那么您应该能够使用IntPtr定义互操作签名,并将该方法的结果传递给

因此,您的签名应该是这样的:

public virtual bool SendData(
    [In] int lChID, 
    [In] short nIndex, 
    [MarshalAs(UnmanagedType.Struct), In] IntPtr vData);
调用代码为:

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.
现在来看,似乎有一些问号。这就是为什么最好的做法通常是让默认的封送处理程序完成它的工作。如果您的vData是字节[],只需使用字节[]定义interop函数,然后查看发生了什么。

签出。假设您知道vData的实际内容应该是什么,那么您应该能够使用IntPtr定义互操作签名,并将该方法的结果传递给

因此,您的签名应该是这样的:

public virtual bool SendData(
    [In] int lChID, 
    [In] short nIndex, 
    [MarshalAs(UnmanagedType.Struct), In] IntPtr vData);
调用代码为:

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.

现在来看,似乎有一些问号。这就是为什么最好的做法通常是让默认的封送处理程序完成它的工作。如果您的vData是byte[],只需用byte[]定义interop函数,然后看看会发生什么。

如果您不确定类型,因为C#没有变量类型,您可以尝试类似以下对象xyz=MyThirdPartyLib.MyThirdPartyLibFunction()的操作:;类型t=类型(xyz);确定引用变量时要使用的类型。。用你的方法/函数替换MyThirdPartyLib.MyThirdPartyLib函数。如果你不知道应该传递什么样的数据类型,那么我们也不会尝试。查找更多使用此功能的示例代码,或向供应商或作者寻求帮助。感谢您的评论。我已经知道C++变体在C语言中没有一对一的定义。我在问题中添加了一个示例代码。它是否拥有所有有价值的信息来为它编写相应的C#代码?谢谢如果您不确定类型,因为C#没有变体类型,您可以尝试类似以下对象xyz=MyThirdPartyLib.MyThirdPartyLibFunction()的操作:;类型t=类型(xyz);确定引用变量时要使用的类型。。用你的方法/函数替换MyThirdPartyLib.MyThirdPartyLib函数。如果你不知道应该传递什么样的数据类型,那么我们也不会尝试。查找更多使用此功能的示例代码,或向供应商或作者寻求帮助。感谢您的评论。我已经知道C++变体在C语言中没有一对一的定义。我在问题中添加了一个示例代码。它是否拥有所有有价值的信息来为它编写相应的C#代码?谢谢,如果我通过字节数组,它能正常工作吗?由于我对编组知之甚少或实际上一无所知,您能举一个例子说明如何使用IntPtr定义互操作签名吗?如果我传递字节数组,它是否可以工作?由于我对编组知之甚少或实际上一无所知,您能举一个例子说明如何使用IntPtr定义互操作签名吗?