Blittable types are data types in software applications which have a unique characteristic. Data are often represented in memory differently in managed and unmanaged code in the Microsoft .NET framework. However, blittable types are defined as having an identical presentation in memory for both environments, and can be directly shared. Understanding the difference between blittable and non-blittable types can aid in using COM Interop or P/Invoke, two techniques for interoperability in .NET applications.
A memory copy operation is sometimes referred to as a 'block transfer'. This term is sometimes abbreviated as BLT (there's actually a BLT instruction on the PDP-10) and pronounced 'blit'. The term 'blittable' expresses whether it is legal to copy an object using a block transfer.
Interoperability can be bidirectional sharing of data and methods between unmanaged code and managed .NET code. .NET provides two ways of interoperating between the two: COM Interop and P/Invoke. Though the methodology is different, in both cases marshalling (conversion between representations of data, formats for calling functions and formats for returning values) must take place. COM Interop deals with this conversion between managed code and COM objects, whereas P/Invoke handles interactions between managed code and Win32 code. The concept of blittable and non-blittable data types applies to both—specifically to the problem of converting data between managed and unmanaged memory. This marshalling is performed by the interop marshaller, which is invoked automatically by the CLR when needed.
Blittable types defined
A blittable type is a data type that does not require special attention from the interop marshaler because by default it has a common representation in managed and unmanaged memory. By pinning the data in memory, the garbage collector will be prevented from moving it, allowing it to be shared in-place with the unmanaged application. This means that both managed and unmanaged code will alter the memory locations of these types in a consistent manner, and much less effort is required by the marshaler to maintain data integrity. The following are some examples of blittable types available in the .NET framework:
Additionally, one-dimensional arrays of these types (including unsafe fixed buffers) as well as complex types containing only instance fields (which includes readonly fields) of these types are blittable. The presence of static or const fields that are non-blittable does not cause the type to become non-blittable, because such fields play no part in marshalling. Complex types (that is structs or classes) must also have instance field layout of Sequential applied using the [StructLayout] attribute in order to be considered blittable by the .net marshaler. Structs have this attribute applied automatically by the compiler, but you must explicitly add it to a class definition if you want an otherwise blittable class to be blittable.
If a type is not one of the blittable types, then it is classified as non-blittable. The reason a type is considered non-blittable is that for one representation in managed memory, it may have several potential representations in unmanaged memory or vice versa. Alternatively, there may be exactly one representation for the type in both managed and unmanaged memory. It is also often the case that there simply is no representation on one side or the other. The following are some commonly used non-blittable types in the .NET framework:
There are many more blittable and non-blittable types, and user-defined types may fit in either category depending on how they are defined (MSDN).
This very restrictive notion of blittable types appears to limit the usefulness of the interoperability services provided by .NET, but this is not so. While blittable types allow a straightforward definition of interoperable types, various ways exist to explicitly define how a non-blittable type should be converted by the interop marshaler. For example, in the .NET languages there are many attributes which can be applied to fields in types, to types themselves and to method parameters to indicate to the marshaler how to handle those particular data. These attributes have various purposes, such as detailing the packing or alignment of a type, specifying offsets of fields in a type, specifying array or string representations, controlling parameter-passing style for function calls, specifying memory management techniques, and more. If none of the attributes or other tools that are provided in the framework are adequate, fine-grained control is provided by the ability to implement the
ICustomMarshaler interface and manually perform the conversion of data in both directions. Complete coverage of interoperation between managed and unmanaged code is out of the scope of this discussion, so please refer to the See Also section for more information. However, understanding what constitutes a blittable type allows a developer to identify situations where intervention is and is not required for a type to be correctly marshaled. In this way, less time is wasted on over-specification of types or function calls.
- "MSDN Magazine - P/Invoke Revisited". Msdn.microsoft.com. Retrieved 2011-12-05.
- "MSDN - Blittable and Non-Blittable Types". Msdn.microsoft.com. Retrieved 2016-02-05.
- "MSDN - Interop Marshaling Overview". Msdn.microsoft.com. Retrieved 2016-02-05.
- "MSDN - .NET Interoperability". Msdn2.microsoft.com. Retrieved 2011-12-05.