将对象的 c# 数组传递给 COM 接口方法

Passing a c# array of object to COM interface method

我应该将对象数组的指针传递给具有以下 IDL 和 C++ 定义的 COM 接口: C++代码:

UpdateItem( LONG lID, LONG lNumOfFields, FieldIdEnum* pFields, VARIANT* pvValues )

IDL:

HRESULT UpdateItem( [in] LONG lID, [in] LONG lNumOfFields, [in, size_is(lNumOfFields)] FieldIdEnum* pFields, [in, size_is(lNumOfFields)] VARIANT* pvValues );

tlbimp 生成的 C# 代码:

UpdateItem([In] int lID, [In] int lNumOfFields, [In] ref FieldIdEnum pFields, [In][MarshalAs(UnmanagedType.Struct)] ref object pvValues);

... 我试着打电话给:

FieldIdEnum[] fieldIDs = { FieldIdEnum.fi1ID, FieldIdEnum.fi2At };
object[] values = { 3, DateTime.UtcNow };
mi.UpdateItem(1, 2, ref fieldIDs[0], ref values[0]);

作为登录和身份验证过程的结果,我从我的系统获得了这个界面...UpdateItem 方法是该界面的 public 成员。

我想通过两个数组(同时)传递两个或多个字段和值对。 字段数组始终正确传递给 C++ 代码。我调试了 C++ 代码,“FieldIdEnum* pFields”代表整数数组的第一个元素,第二个元素 (pFields1) 也是正确的。 pField[] 是一个 c 风格的数组。

但是第二个数组是一个具有各种元素类型的变体数组,在本例中是一个整数和一个日期时间。这在 C++ 端显示为 SafeArray 而不是 c_style 数组。我也检查了这个第二个数组,如果方法调用从另一个 C 代码开始,它是一个简单的变体数组,但 C# 试图将它编组到 safearray。

我已将 C# 定义更改为

UpdateItem([In] int lID, [In] int lNumOfFields, [In] ref FieldIdEnum pFields, [In] ref object pvValues);

它不起作用我总是收到“值不在预期范围内”之类的异常。 “System.Exception {System.ArgumentException}”

我试过 use/marshal 各种 managed/unmanaged 类型和 Intptr,没有用。

我发现 other topic 有 same/similar 问题,我无法让它工作。

如何将对象数组的指针传递给 COM 接口?

我找到了解决办法。 我重新定义了接口方法:

        void UpdateItem([In] int lID, [In] int lNumOfFields, [In] ref FieldIdEnum pFields, [In][MarshalAs(UnmanagedType.LPArray)] object[] pvValues);

...并将其称为:

            FieldIdEnum[] updateFieldIDs = { FieldIdEnum.fi1ID, FieldIdEnum.fi2At };
            object[] values = { 3, DateTime.UtcNow };
            
            mi.UpdateItem(id, updateFieldIDs.Length, ref updateFieldIDs[0], values);

感谢指导。