【发布时间】: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