用托管代码编写的 Vspackage 可能必须调用或由非托管 COM 代码调用。 通常,方法参数由 interop 封送拆收器转换或位置,自动。 但是,参数不能在某些情况下转换以简单方式。 在这些情况下,互操作程序集的方法原型参数用于尽可能密切地符合 COM 函数参数。 有关更多信息,请参见 互操作封送处理。
常规建议
读取参考文档
如果启用了检测互操作性问题将读取每个方法的参考文档。
每个方法的参考文档包含三个相关部分:
Visual C++ COM 函数原型。
互操作程序集方法原型。
COM 参数和每个的简短说明的列表。
查找两个原型之间的差异
大多数互操作性问题从定义的不匹配派生之间特定类型的 COM 接口,并相同的定义输入 Visual Studio 互操作程序集。 例如,请考虑在能够差异通过在个参数的 null [out] 值。 您必须位于两个原型之间的差异以及考虑其传递的数据的后果。
读取参数定义
读取参数定义。 COM 比有关组合不同数据类型的公共语言 (CLR)运行时不太强在单个参数的。 Visual Studio COM 接口利用此灵活性的。 可以通过或需要一个非标准值或数据的类型,如指针参数的常数值应描述的所有参数,如下例所示在文档。
为类型传递的对象无效 IUnknown **
查找 [out] 定义为 COM 接口的类型 void ** ,但是,定义为 [在 Visual Studio 互操作程序集方法原型的iid_is] 的参数。
在某些情况下, COM 接口生成一 IUnknown 对象,并且, COM 接口然后将它作为类型 void **。 这些接口尤其重要,因为,如果变量是在 [out] IDL 中定义,然后 IUnknown 对象引用计数。 AddRef 方法。 ,如果对象不正确,将处理内存泄漏发生。
备注
; 如果没有显式释放,在变量中创建的 COM [out] 接口和返回的 IUnknown 对象会导致内存泄漏它。
托管方法处理这些对象应视为 IntPtr 作为指向 IUnknown 对象,并调用 GetObjectForIUnknown 方法获取对象。 调用方应然后将返回值强制转换为任何类型正确。 当不再需要某个对象时,调用 Release 释放。
以下正确调用 QueryViewInterface 方法和处理 IUnknown 对象的示例:
MyClass myclass;
Object object;
IntPtr pObj;
Guid iid = Typeof(MyClass).Guid;
int hr = windowFrame.QueryViewInterface(ref iid, out pObj);
if (NativeMethods.Succeeded(hr))
{
try
{
object = Marshal.GetObjectForIUnknown(pObj);
myclass = object;
}
finally
{
Marshal.Release(pObj);
}
}
else
{
// error calling QueryViewInterface
}
备注
以下方法识别通过 IUnknown 对象指针为类型 IntPtr。处理它们如本节所述。
可选参数 [out]
查找已定义的参数,当数据类型 [out] (int, object,等等) COM 接口,但是,定义为数组相同的数据类型 Visual Studio 互操作程序集方法原型。
某些 COM 接口,如 GetCfgs,将 [out] 参数标记为可选。 如果不需要对象,这些 COM 接口返回 null 指针作为该参数的值而不是创建 [out] 对象。 这是设计使然。 作为 VSPackage 中正确的行为的一部分,对于这些接口, null 指针,假设,并将错误不返回。
由于 CLR 不允许参数的值 [out] 是 null的一部分,通过这些接口旨在的行为在托管代码中不直接可用。 受影响的接口的 Visual Studio 互操作程序集方法在解决问题工作项定义相关参数旁边为数组,因为 CLR 通过 null 数组。
,当 nothing 返回时,这些方法的托管实现应将 null 数组赋给该参数。 否则,请创建正确类型的单个元素的数组并将返回值数组中。
获取从接口的信息带可选参数的托管方法 [out] 接收该参数作为数组。 请检查数组的第一个元素的值。 如果不是 null,将第一个元素,就好像它是原始参数。
通过在指针参数的常数
查找定义为 COM [in] 接口的指针,但是,定义为 IntPtr 输入 Visual Studio 互操作程序集原型方法的参数。
类似发生问题,当 COM 接口通过特定值,如 0, -1,即 – 2,而不是对象指针。 不同 Visual C++, CLR 不允许常数转换为对象。 相反, Visual Studio 互操作程序集中定义参数作为 IntPtr 类型。
这些方法的托管实现应利用该条件 IntPtr 类具有 int 和创建 void * 的构造函数对象或整型常数的 IntPtr ,根据。
接收此类型的 IntPtr 参数的托管方法应使用 IntPtr 类型转换运算符处理结果。 首先将 IntPtr 为 int 并测试代码相关的整数常数。 如果值不匹配,请将其转换为所需类型的对象并继续 "。
在此操作的示例,请参见 OpenStandardEditor 和 OpenSpecificEditor。
OLE 返回作为 [out] 参数传递的值
查找具有 retval 返回值 COM 接口,但是,使 int 返回值和一个附加的数组 [out] 参数在 Visual Studio 互操作程序集方法原型的方法。 应清楚这些方法需要特殊处理,因为 Visual Studio 互操作程序集原型方法比 COM 接口方法还具有一个参数。
处理 OLE 事件的许多 COM 接口将有关 OLE 状态的信息到 retval 存储的调用过程返回接口的值。 而不是使用返回值,对应的 Visual Studio 互操作程序集方法将信息添加到数组参数存储的 [out] 调用的过程。
这些方法的托管实现在参数应创建类型的单个元素的数组和 [out] 参数相同并将其放在。 数组元素的值应与适当的 COM retval。
调用此类型的接口的托管方法应从数组中的第一个 [out] 元素。 此元素可以处理,就象它 retval 返回从相应的 COM 接口的值。