从C#调用具有VARIANT参数类型的托管API方法
本文关键字:API 方法 类型 参数 调用 VARIANT | 更新日期: 2023-09-27 18:23:35
我有一个ActiveX DLL,我试图在C#应用程序中使用它。大多数互操作方法都有效。我对以下方法(非托管定义)有问题:
HRESULT SendData([in] long lChID, [in] short nIndex,
[in] VARIANT vData, [out, retval] VARIANT_BOOL *bResult);
VARIANT数据类型对我来说很不寻常,我不知道该怎么处理它,因为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。
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#中有相应的代码吗?
检查System.Runtime.InteropServices.Marshal.GetNativeVariantForObject()
方法。假设您知道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[]定义互操作函数,然后看看会发生什么。