【问题标题】:Passing a c# array of object to COM interface method将 c# 对象数组传递给 COM 接口方法
【发布时间】:2022-01-12 21:27:04
【问题描述】:

我应该将对象数组的指针传递给具有以下 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 方法是该接口的公共成员。

我想通过两个数组传递两个或多个字段和值对(同时)。 字段数组始终正确传递给 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}”

我尝试使用/编组各种托管/非托管类型和 Intptr,但没有成功。

我发现other topic 有相同/相似的问题,我无法让它工作。

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

【问题讨论】:

  • 你可以控制界面吗? SAFEARRAY 将自动在托管代码中工作。不过,更像是本地人的熊。否则,我希望您必须将IntPtr 的数组手动填充为Marshal.GetIUnknownForObject 并传递该地址。我不确定object[][MarshalAs(UnmanagedType.LPArray)] 的编组是什么。
  • 当你想传递一个数组时,只需传递一个 [In] VARIANT* 参数,并在 idl 中删除你的 size_is 属性(更多用于 C 风格的非自动化接口)。然后从 .NET 使用任何对象 [] 作为输入。
  • 很遗憾,我无法更改 COM/IDL 代码,因为它在其他 C/C++/Delphi 应用程序中使用...

标签: c# c++ com marshalling


【解决方案1】:

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

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

感谢您的指导。

【讨论】:

    猜你喜欢
    • 2012-08-21
    • 2018-07-29
    • 2012-05-25
    • 2012-08-29
    • 1970-01-01
    • 1970-01-01
    • 2018-08-10
    • 1970-01-01
    相关资源
    最近更新 更多