自定义 COM 可调用包装

更新:2007 年 11 月

自定义 COM 可调用包装是一项简单的任务。如果要向 COM 客户端公开的类型具有非标准封送处理要求,则将 System.Runtime.InteropServices.MarshalAsAttribute 属性应用于方法参数、类字段或者返回值以更改封送处理行为。

如下面的插图所示,可以导出托管 DLL 而不自定义包装(如图左侧所示)。或者,可以向源代码添加封送处理信息,编译它,然后使用类型库导出程序 (Tlbexp.exe) 导出修改后的 DLL 并产生自定义包装。

导出的 DLL 中的封送处理信息

类型库导出程序

说明:

要向 COM 公开的所有托管类型、方法、属性、字段和事件都必须是公共的。类型必须具有公共的默认构造函数,该构造函数是唯一可以通过 COM 调用的构造函数。有关其他信息,请参见为互用性限定 .NET 类型

在托管和非托管代码之间封送数据时,interop 封送拆收器必须识别正在传递的数据的表示形式:

  • 对于可直接复制到本机结构中的类型,托管和非托管表示形式始终是相同的。例如,4 字节整数始终被封送为 4 字节整数。interop 封送拆收器使用托管签名确定数据的表示形式。

  • 对于非直接复制到本机结构中的类型,interop 封送拆收器根据其方法签名识别托管表示形式,但无法根据方法签名识别非托管表示形式。若要封送非直接复制到本机结构中的类型,可以使用下列技术中的一种:

    • 允许封送拆收器从托管表示形式推断表示形式。

    • 显式提供非托管数据的表示形式。

例如,当从托管代码到非托管代码进行封送时,字符串将被转换为 BSTR 类型,除非显式应用 MarshalAsAttribute 将字符串封送到其他类型(如 LPWSTR)。可以将该属性应用到类型定义的源代码中的参数、字段或返回值,如下例中所示。

将 MarshalAsAttribute 应用到参数

Public Sub M1
(<MarshalAs(UnmanagedType.LPWStr)> msg As String)
public void M1
([MarshalAs(UnmanagedType.LPWStr)]String msg);

将 MarshalAsAttribute 应用到类中的字段

Class MsgText
<MarshalAs(UnmanagedType.LPWStr)> Public msg As String
End Class
class MsgText {
[MarshalAs(UnmanagedType.LPWStr)] Public String msg;
}

将 MarshalAsAttribute 应用到返回值

Public Function M2() _
As <MarshalAs(UnmanagedType.LPWStr)> String
[return: MarshalAs(UnmanagedType.LPWStr)]
public String GetMessage();

可以设置 System.Runtime.InteropServices.UnmanagedType 枚举以指示所需的非托管类型的格式。在前面的签名中,msg 数据被作为 Unicode 字符 (LPWStr) 的以 null 终止的缓冲区进行封送处理。

有时,interop 封送拆收器需要的信息比托管和非托管数据格式所提供的信息多。例如,若要封送数组,必须提供元素类型、秩、大小和数组的界限。可以使用 MarshalAsAttribute 指定所需的附加信息。

请参见

概念

COM 数据类型

自定义运行库可调用包装

参考

自定义 COM 可调用包装

其他资源

用 COM Interop 对数据进行封送处理

默认封送处理行为