P/Invoke概览
P/Invoke连接了两种不同类型的代码:托管代码和非托管代码1。换句话说,它为.NET精简框架下的程序提供了一条调用本地操作系统功能的途径。在深入P/Invoke之前,我们需要讨论一下托管代码和非托管代码的不同。表4.1总结了这些重要的不同点。
表 4.1. 托管代码和非托管代码的比较
|
特性 |
托管代码 |
非托管代码 |
|
别名 |
可移植代码 安全代码 .NET代码 C# 代码, Visual Basic .NET 代码 |
本地代码 非安全代码 Win32代码 C代码, C++代码 |
|
特性 |
托管代码 |
非托管代码 |
|
语言支持 |
C#, Visual Basic .NET (在.NET精简框架中) |
C, C++ |
|
.exe/.dll文件格式 |
通用中间语言(CIL),一个与CPU独立的机器级别的语言,在运行时转换成本地的机器指令 |
针对目标处理器的本地机器语言,这些目标处理器如:SH3, SH4, MIPS, StrongARM, XScale, x86 |
|
内存管理 |
当需要时,由通用语言运行时提供 |
当一个过程中止时,自动清除Win32对象;否则,由应用程序(或者驱动)代码负责清理内存和Win32对象 |
|
安全性检查 |
有 |
无 |
|
数组越界保护 |
有 |
无 |
|
对指针的支持 |
内建的隐含指针支持,当显式的使用指针时需要使用unsafe关键字;Marshal[a]类支持创建传入非托管代码的指针 |
显式的指针被广泛应用 |
[a] 全称为: System.Runtime.InteropServices.Marshal。
托管代码是可移植代码,这是因为.NET的可执行程序能够运行在任何已经安装了相应的通用语言运行时(CLR)的平台上,而不管是哪种CPU。托管代码也是安全代码,因为它有一整套特性来避免令人烦恼的非托管代码中存在的问题。这些特性包括:隐式指针,可以消除内存泄漏的自动内存管理和防止内存越界的数组边界保护。我们有时会使用术语“.NET代码”,因为托管代码直接依赖于.NET精简框架中提供的编程接口。
非托管代码还有其它许多称呼。这些名字都反映了一个以.NET为中心的看待非托管代码的方式,并且突出了通用语言运行时的一些优越之处。通过解析非托管代码,我们在表4.1中列出了在每项非托管代码中,与托管代码相关的或者隐含的概念。
非托管代码有时被称为本地代码(Native code),是因为可执行文件格式不是可移植的、指向通用语言运行时提供服务的IL格式,而是本地的处理器指令集,如SH3或者StrongARM处理器。而又有的时候非托管代码被称作非安全的代码(Unsafe code)是因为它缺少对内存泄漏、“坏”指针和数组越界的保护机制,而这些机制都在通用语言运行时中已被提供。还有的时候我们称之为Win32代码则是因为这些DLL经常(但不是总是)直接被创建成Win32 API。Win32 API为每个版本的Windows提供基础接口。






