目录
托管和本机代码互操作适用哪种场合?
互操作技术:三种选择
互操作技术:P/Invoke
互操作技术:COM Interop
互操作技术:C++/CLI
互操作体系结构注意事项
API 设计和开发人员体验
互操作边界的性能和位置
生存期管理
托管和本机代码互操作适用哪种场合?
有关使用托管和本机代码互操作适宜时机的论述并不多,现有的论述也以自相矛盾者居多。有时,指南还缺乏实践体验做依据。因此,我先声明我编写的这个指南以我们互操作团队的实践经验为基础,它已向各类内部和外部客户提供过帮助。
在总结这一经验时,我们采纳了三种产品,由它们充当成功使用互操作和典型使用方式的上佳示例。提及互操作时,我首先想到的应用程序就是 Visual Studio Tools for Office,它是 Office 的托管扩展性工具集。它代表互操作的一种典型使用情况——一个想要启用托管扩展或加载项的大型应用程序。另一个就是 Windows Media Center,从一开始,它就是一个混合了托管和本机的应用程序。开发 Windows Media Center 主要使用的是托管代码和本机代码中内置的一些内容,即负责直接处理 TV 调谐器和其他硬件驱动程序的代码段。最后是 Expression Design,一个具备大型预置本机代码库的应用程序,它计划利用 Windows Presentation Foundation (WPF) 这一新的托管技术,提供全新的用户体验。
这三个应用程序解释了使用互操作的三个最普遍的原因:让原有的本机应用程序具备托管扩展性;让应用程序的大部分内容能利用托管代码的优点,同时又能在本机代码中编写最基础的代码段;为现有本机应用程序注入全新的用户体验。
过去,指南中给出的对策是用托管代码彻底重新编写应用程序。采纳这一建议并目睹许多人将其拒之门外之后,您会清楚这一方案对于大部分现有应用程序来说都不适用。互操作非常有助于开发人员维护其在本机代码中的投资,同时还能让他们利用新的托管环境。如果您由于其他原因计划重新编写应用程序,托管代码是个不错的选择。但一般而言,您不想只为使用新的托管技术而重新编写程序,因此也就谈不上互操作。
互操作技术:三种选择
.NET Framework 中有三种主要的互操作技术,具体选用哪种由您用于互操作的 API 类型及控制边界的要求和需要决定。Platform Invoke(或 P/Invoke)基本上是从托管到本机的互操作技术,您可以用它从托管代码调用 C 类本机 API。您还可以使用 COM interop 技术从托管代码使用本机 COM 接口,或从托管 API 导出本机 COM 接口。最后是 C++/CLI(先前称为托管 C++),它允许您创建包含托管和本机 C++ 混合编译代码的程序集,该程序集旨在为托管代码和本机代码搭建起沟通的桥梁。
互操作技术:P/Invoke
P/Invoke 是三种技术中最简单的一个,它的主要功能是让托管代码能访问 C 类 API 。使用 P/Invoke 时,您需要分别封装每个 API。如果要封装的 API 数量不多且其签名也不复杂,这是个不错的选择。但是,如果 API 有很多参数,且这些参数没有好的托管对等项,如变量长度结构、void *、重叠的共同体等,那么 P/Invoke 使用起来会相当难。
.NET Framework 基类库 (BCL) 包含 API 的多个示例,它们就是多个 P/Invoke 声明外部厚实的包装。在包装非托管 Windows API 的 .NET Framework 中,几乎所有功能都是使用 P/Invoke 构建的。实际上,即便是 Windows 窗体,也差不多完全是使用 P/Invoke 在本机 ComCtl32.dll 基础上构建的。
这里有几个非常有用的资源,可以极大地降低 P/Invoke 的使用难度。首先,pinvoke.net 网站上有一个 wiki,最初是由 CLR 互操作团队的 Adam Nathan 设置的,里面有大量由用户为各种通用 Windows API 贡献的签名。
还有非常便于使用的 Visual Studio 加载项,利用它可以轻松从 Visual Studio 访问 pinvoke.net。对于 pinvoke.net 上没有的 API(可能是您自己或他人库中的 API),互操作团队已发布了一个 P/Invoke 签名生成工具,称为 P/Invoke Interop Assistant,它能根据头文件自动为本机 API 创建签名。随附的截图显示了处于使用状态的工具。