ECMA-335 (CLI) 标准 读书笔记——总结CLI类型系统(上)
标准的第四部指出,CLI的核心是Kernel Profile,而Kernel Profile由Runtime infrastructure library和Base Class Library (BCL) 组成。
· Runtime infrastructure library 向CLI提供了编译器需要的服务和从特定格式的文件流中动态调用类型的能力,CLI规范的第二部中指定了这些特定的文件格式。
· BCL是现代编程语言的一个简单的运行时库,它作为C#语言运行时库的标准,同时也作为CLI标准库的一部分。它提供了类型来描述CLI的内建数据类型,简单的文件存取,定制属性,安全属性,字符串处理,格式化,流,集合等等。
这里我们可以看出支持CLI核心特征的Runtime infrastructure library主要由指令系统构成,而BCL则主要由类型系统构成。所以我们研究CLI的核心就要从它的指令系统和类型系统入手。
我们先来总结一下CLI的类型系统。
通用类型系统的概述请参考:ECMA- 335(CLI)标准 读书笔记(第一部:概念和架构 第8章~8.2)
类型分为值类型和引用类型。
值类型分为内建值类型和用户定义类型。
引用类型分为自描述、接口、指针和内建引用类型。
类型系统里最核心的是内建类型,包括内建值类型和引用类型。其它的特征则可以根据不同的系统平台要求在实现时进行裁减。
第二部 第7章 类型和签名
元数据提供了定义和引用类型的机制。第10章描述了与类型定义相关的元数据,这里不区分类型是类,接口还是值类型。
用于引用类型的机制分为以下两部分:
· 用户定义类型的逻辑描述,该类型被引用但没定义在当前模块中,它们被存储于元数据的表中(22.38章)。
· 编码一个或更多类型引用的签名,除了多种修饰语外。语法非终结符的Type描述了签名中的独特入口。签名的编码在23.1.16章详述。
7.1 内建类型
下面的表详细列出了CLI中所有的内建类型(包括指针类型):
Type ::= |
Description |
Clause |
‘!’ Int32 |
Generic parameter in a type definition, accessed by index from 0 |
9.1 |
| ‘!!’ Int32 |
Generic parameter in a method definition, accessed by index from 0 |
9.2 |
| bool |
Boolean |
7.2 |
| char |
16-bit Unicode code point |
7.2 |
| class TypeReference |
User defined reference type |
7.3 |
| float32 |
32-bit floating-point number |
7.2 |
| float64 |
64-bit floating-point number |
7.2 |
| int8 |
Signed 8-bit integer |
7.2 |
| int16 |
Signed 16-bit integer |
7.2 |
| int32 |
Signed 32-bit integer |
7.2 |
| int64 |
Signed 64-bit integer |
7.2 |
| method CallConv Type ‘*’ ‘(’ Parameters ‘)’ |
Method pointer |
14.5 |
| native int |
32- or 64-bit signed integer whose size is platform-specific |
7.2 |
| native unsigned int |
32- or 64-bit unsigned integer whose size is platform-specific |
7.2 |
| object |
See System. Object in Partition IV |
|
| string |
See System.String in Partition IV |
|
| Type ‘&’ |
Managed pointer to Type. Type shall not be a managed pointer type or typedref |
14.4 |
| Type ‘*’ |
Unmanaged pointer to Type |
14.4 |
| Type ‘<’ GenArgs ‘>’ |
Instantiation of generic type |
9.4 |
| Type ‘[’ [ Bound [ ‘,’ Bound ]*] ‘]’ |
Array of Type with optional rank (number of dimensions) and bounds. |
14.1and 14.2 |
| Type modopt ‘(’ TypeReference ‘)’ |
Custom modifier that can be ignored by the caller. |
7.1.1 |
| Type modreq ‘(’ TypeReference ‘)’ |
Custom modifier that the caller shall understand. |
7.1.1 |
| Type pinned |
For local variables only. The garbage collector shall not move the referenced value. |
7.1.2 |
| typedref |
Typed reference (i.e., a value of type System.TypedReference), created by mkrefany and used by refanytype or refanyval. |
7.2 |
| valuetype TypeReference |
(Unboxed) user defined value type |
13 |
| unsigned int8 |
Unsigned 8-bit integer |
7.2 |
| unsigned intl6 |
Unsigned l6-bit integer |
7.2 |
| unsigned int32 |
Unsigned 32-bit integer |
7.2 |
| unsigned int64 |
Unsigned 64-bit integer |
7.2 |
| void |
No type. Only allowed as a return type or as part of void * |
7.2 |
7.4 本地数据类型
CLI的一些实现将运行于现有的操作系统或运行时平台上,这些平台指定的数据类型要执行某些特定的功能。元数据允许通过指定CLI的内建和用户定义类型如何被转换成本地数据或者从本地数据转换过来的方式,与这些本地数据类型进行交互。这些转换信息能被(使用关键词marshal)用于:
- 方法的返回类型,规定了一个本地数据类型实际被返回的和应该被转换回指定的CLI数据类型。
- 方法的参数,规定了被调用者提供的CLI数据类型应该被转换成指定的本地数据类型。(如果参数通过引用传递,更新的值应该在调用结束后,从本地数据类型被转换回CLI类型。)
- 用户定义类型字段,规定了任何企图传递包含该字段的对象的时候,平台方法都应该作一份这个对象的拷贝,用指定的本地数据类型替换这些字段。(如果对象通过引用被传递,更新的值应该在调用结束后被转换回来。)
下面的表中列出了CLI支持的所有本地类型,并提供了每个类型的描述。(更多完整的描述请看第四部分中enum的定义System.Runtime.Interopservices.UnmanagedType,它提供了用于编码这些类型的实际值。)所有0-63的编码值被保留用于向后兼容所有已经存在的CLI的执行。64-127的值被留作将来用于这个和相关标准上。
NativeType ::= |
Description |
Name in the class library enum type UnmanagedType |
‘[’ ‘]’ |
Native array. Type and size are determined at runtime from the actual marshaled array. |
LPArray |
|bool |
Boolean. 4-byte integer value where any non- zero value represents TRUE, and 0 represents FALSE. |
Bool |
| float32 |
32-bit floating-point number. |
R4 |
| float64 |
64-bit floating-point number. |
R8 |
| [unsigned] int |
Signed or unsigned integer, sized to hold a pointer on the platform |
SysUInt or SysInt |
| [unsigned] int8 |
Signed or unsigned 8-bit integer |
U1 or I1 |
| [unsigned] int16 |
Signed or unsigned 16-bit integer |
U2 or I2 |
| [unsigned] int32 |
Signed or unsigned 32-bit integer |
U4 or I4 |
| [unsigned] int64 |
Signed or unsigned 64-bit integer |
U8 or I8 |
|lpstr |
A pointer to a null-terminated array of ANSI characters. The code page is implementation- specific. |
LPStr |
|lpwstr |
A pointer to a null-terminated array of Unicode characters. The character encoding is implementation-specific. |
LPWStr |
| method |
A function pointer. |
FunctionPtr |
| NativeType ‘[’ ‘]’ |
Array of NativeType. The length is determined at runtime by the size of the actual marshaled array. |
LPArray |
| NativeType ‘[’ Int32 ‘]’ |
Array of Native Type of length lnt32. |
LPArray |
| NativeType ‘[’ ‘+’ Int32 ‘]’ |
Array of NativeType with runtime supplied element size. The int32 specifies a parameter to the current method (counting from parameter number 0) that, at runtime, will contain the size of an element of the array in bytes. Can only be applied to methods, not fields. |
LPArray |
| NativeType ‘[’ Int32 ‘+’ Int32 ‘]’ |
Array of NativeType with runtime supplied element size. The first int32 specifies the number of elements in the array. The second 1nt32 specifies which parameter to the current method (counting from parameter number 0) will specify the additional number of elements in the array. Can only be applied to methods, not fields |
LPArray |
[例子:
.method int32 M1( int32 marshal(int32), bool[] marshal(bool[5]) )
方法 M1 带了两个参数: 一个int32和一个带有5个 bool的数组.
.method int32 M2( int32 marshal(int32), bool[] marshal(bool[+1]) )
方法M2带了两个参数: 一个 int32和一个 bool型数组: 数组元素的个数由第一个参数的值给定。
.method int32 M3( int32 marshal(int32), bool[] marshal(bool[7+1]) )
方法M3带了两个参数: 一个int32和一个 bool型数组: 数组元素的个数由第一个参数的值加上7给定.]