.NET has a variety of formats for marshalling strings. These methods are split into distinct sections on C-style strings and Windows-centric string formats.
C-style strings
Each of these formats passes a null-terminated string to native code. They differ by the encoding of the native string.
System.Runtime.InteropServices.UnmanagedType value
Encoding
LPStr
ANSI
LPUTF8Str
UTF-8
LPWStr
UTF-16
LPTStr
UTF-16
The UnmanagedType.VBByRefStr format is slightly different. Like LPWStr, it marshals the string to a native C-style string encoded in UTF-16. However, the managed signature has you pass in the string by reference and the matching native signature takes the string by value. This distinction allows you to use a native API that takes a string by value and modifies it in-place without having to use a StringBuilder. We recommend against manually using this format since it's prone to cause confusion with the mismatching native and managed signatures.
Windows-centric string formats
When interacting with COM or OLE interfaces, you'll likely find that the native functions take strings as BSTR arguments. You can use the UnmanagedType.BStr unmanaged type to marshal a string as a BSTR.
If you're interacting with WinRT APIs, you can use the UnmanagedType.HString format to marshal a string as an HSTRING.
Customizing array parameters
.NET also provides you multiple ways to marshal array parameters. If you're calling an API that takes a C-style array, use the UnmanagedType.LPArray unmanaged type. If the values in the array need customized marshalling, you can use the ArraySubType field on the [MarshalAs] attribute for that.
On Windows, the .NET runtime provides a number of different ways to marshal object parameters to native code.
Marshalling as specific COM interfaces
If your API takes a pointer to a COM object, you can use any of the following UnmanagedType formats on an object-typed parameter to tell .NET to marshal as these specific interfaces:
IUnknown
IDispatch
IInspectable
Additionally, if your type is marked [ComVisible(true)] or you're marshalling the object type, you can use the UnmanagedType.Interface format to marshal your object as a COM callable wrapper for the COM view of your type.
Marshalling to a VARIANT
If your native API takes a Win32 VARIANT, you can use the UnmanagedType.Struct format on your object parameter to marshal your objects as VARIANTs. See the documentation on customizing object fields for a mapping between .NET types and VARIANT types.
Custom marshallers
If you want to project a native COM interface into a different managed type, you can use the UnmanagedType.CustomMarshaler format and an implementation of ICustomMarshaler to provide your own custom marshalling code.
Collaborate with us on GitHub
The source for this content can be found on GitHub, where you can also create and review issues and pull requests. For more information, see our contributor guide.
.NET
feedback
.NET
is an open source project. Select a link to provide feedback:
This module covers method parameters, including pass-by-reference and pass-by-value parameter types. This module also covers optional and named arguments.