Skip to content

Latest commit

 

History

History
74 lines (56 loc) · 3.54 KB

ii.23.4-marshalling-descriptors.md

File metadata and controls

74 lines (56 loc) · 3.54 KB

II.23.4 Marshalling descriptors

A Marshalling Descriptor is like a signature – it's a 'blob' of binary data. It describes how a field or parameter (which, as usual, covers the method return, as parameter number 0) should be marshalled when calling to or from unmanaged code via PInvoke dispatch. The ILAsm syntax marshal can be used to create a marshalling descriptor, as can the pseudo custom attribute MarshalAsAttribute – see §II.21.2.1)

Note that a conforming implementation of the CLI need only support marshalling of the types specified earlier – see §II.15.5.4.

Marshalling descriptors make use of constants named NATIVE_TYPE_xxx. Their names and values are listed in the following table:

Name Value
NATIVE_TYPE_BOOLEAN 0x02
NATIVE_TYPE_I1 0x03
NATIVE_TYPE_U1 0x04
NATIVE_TYPE_I2 0x05
NATIVE_TYPE_U2 0x06
NATIVE_TYPE_I4 0x07
NATIVE_TYPE_U4 0x08
NATIVE_TYPE_I8 0x09
NATIVE_TYPE_U8 0x0a
NATIVE_TYPE_R4 0x0b
NATIVE_TYPE_R8 0x0c
NATIVE_TYPE_LPSTR 0x14
NATIVE_TYPE_LPWSTR 0x15
NATIVE_TYPE_INT 0x1f
NATIVE_TYPE_UINT 0x20
NATIVE_TYPE_FUNC 0x26
NATIVE_TYPE_ARRAY 0x2a

The 'blob' has the following format

MarshalSpec ::=
NativeIntrinsic
| ARRAY ArrayElemType
| ARRAY ArrayElemType ParamNum
| ARRAY ArrayElemType ParamNum NumElem
NativeIntrinsic ::=
BOOLEAN | I1 | U1 | I2 | U2 | I4 | U4 | I8 | U8 | R4 | R8 | LPSTR | LPSTR | INT | UINT | FUNC

For compactness, the NATIVE_TYPE_ prefixes have been omitted in the above lists; for example, ARRAY is shorthand for NATIVE_TYPE_ARRAY.

ArrayElemType ::=
NativeIntrinsic

ParamNum is an unsigned integer (compressed as described in §II.23.2) specifying the parameter in the method call that provides the number of elements in the array – see below.

NumElem is an unsigned integer (compressed as described in §II.23.2) specifying the number of elements or additional elements – see below.

[Note: For example, in the method declaration:

.method void M(int32[] ar1, int32 size1, unsigned int8[] ar2, int32 size2) { … }

The ar1 parameter might own a row in the FieldMarshal table, which indexes a MarshalSpec in the Blob heap with the format:

ARRAY  MAX  2  1

This says the parameter is marshalled to a NATIVE_TYPE_ARRAY. There is no additional info about the type of each element (signified by that NATIVE_TYPE_MAX). The value of ParamNum is 2, which indicates that parameter number 2 in the method (the one called size1) will specify the number of elements in the actual array – let's suppose its value on a particular call is 42. The value of NumElem is 0. The calculated total size, in bytes, of the array is given by the formula:

if ParamNum = 0
   SizeInBytes = NumElem * sizeof (elem)
else
   SizeInBytes = ( @ParamNum +  NumElem ) * sizeof (elem)
endif

The syntax @ParamNum is used here to denote the value passed in for parameter number ParamNum – it would be 42 in this example. The size of each element is calculated from the metadata for the ar1 parameter in Foo's signature – an ELEMENT_TYPE_I4II.23.1.16) of size 4 bytes. end note]