交互操作的一般注意事项
更新:2007 年 11 月
在托管代码和非托管代码之间进行的所有调用都必须满足各自编程模型强加的要求。托管和非托管编程模型在很多方面是不同的。下表显示了每个模型的定义特征。
特征 |
非托管模型 |
托管模型 |
---|---|---|
编码模型 |
基于接口 |
基于对象 |
标识 |
GUID |
强名称 |
错误处理机制 |
HRESULT |
异常 |
类型兼容性 |
二进制标准 |
类型标准 |
类型定义 |
类型库 |
元数据 |
类型安全 |
非类型安全 |
可选安全 |
版本控制 |
不可变的 |
灵活的 |
某些编程模型特征具有可以查看的关联实体,如类型库和元数据。某些可作为参数传递,如 GUID 和强名称。其他特征则更具有概念性:您肯定会考虑它们对应用程序设计的影响,但对于这些特征您不会遇到在托管和非托管模型之间的直接映射。
以下各节更为详细地解释了每个特征。
编码模型
非托管对象总是通过接口进行通信;托管对象和类则可以直接传递数据,而无需实现接口。默认情况下,在对象或类没有实现接口时,COM 互操作 将生成一个类接口以便通过接口向 COM 公开托管功能。
错误处理机制
COM 方法通常返回 HRESULT,指示调用成功还是失败。托管代码包含异常。默认情况下,COM 互操作 将托管异常映射为指示失败的 HRESULT。标识
GUID 标识特定的非托管类型,并且不会为该类型提供任何位置信息。除类型名称外,强名称还包含唯一的程序集名称。由于程序集名称唯一地标识类型,因此可以跨多个程序集重用某一类型名称。程序集还向托管类型引入出版商密钥、版本和位置信息。交互操作服务生成 GUID,并按要求提供强名称。纯旧数据结构 (PODS)
如果结构或类包含构造函数,则平台调用无法用来通过值返回结构或类。一般来说,包含非 PODS 元素的用户定义类型应通过引用返回。根据 ISO/IEC 标准 14882“Programming Languages — C++”(编程语言 — C++)的定义,PODS 是仅包含字段值的被动集合的数据结构。它们不包含构造函数、复制赋值运算符、析构函数,或者本身不是 PODS 的非静态数据成员。类型兼容性
类型在托管代码和非托管代码之间是不同的,同时还随语言的不同而不同。类型定义
如果您习惯使用类型库,您就会知道类型库只包含公共类型。而且,类型库是可选的。在托管编程模型中,类型信息对于所有类型都是强制的。交互操作服务提供用于将类型库转换为程序集中的元数据以及将元数据转换为类型库的工具。类型安全
非托管编译器不对指针类型提供任何类型检查,从而使代码容易受到潜在危害性活动的影响。通常情况下,托管代码需要更高的信任级别。尽管托管代码由于其不安全的行为而受到一些限制,程序员仍可以继续在托管代码中使用指针。交互操作服务禁止不受信任的托管代码访问非托管代码。版本控制
COM 接口是不可变的。如果要更改接口,必须使用新的 GUID 对其进行重命名。托管类型可以使用同一名称进行演化。