Charsets and marshalling


The following guidance is for [DllImport] use and must be manually followed for correct results. .NET 7+ users should consider using [LibraryImport] instead. An in-box Roslyn analyzer (enabled by default) will provide required guidance for the [LibraryImport] attribute in your code.

The way char values, string objects, and System.Text.StringBuilder objects are marshalled depends on the value of the CharSet field on either the P/Invoke or structure. You can set the CharSet of a P/Invoke by setting the DllImportAttribute.CharSet field when declaring your P/Invoke. To set the CharSet for a type, set the StructLayoutAttribute.CharSet field on your class or struct declaration. When these attribute fields are not set, it is up to the language compiler to determine which CharSet to use. C#, Visual Basic, and F# use the None charset by default, which has the same behavior as the Ansi charset.

If the System.Runtime.InteropServices.DefaultCharSetAttribute is applied on the module in C# or Visual Basic code, then the C# or Visual Basic compiler will emit the provided CharSet by default instead of using CharSet.None. F# does not support the DefaultCharSetAttribute, and always emits CharSet.None by default.

The following table shows a mapping between each charset and how a character or string is represented when marshalled with that charset:

CharSet value Windows .NET Core 2.2 and earlier on Unix .NET Core 3.0 and later and Mono on Unix
Ansi char (the system default Windows (ANSI) code page) char (UTF-8) char (UTF-8)
Unicode wchar_t (UTF-16) char16_t (UTF-16) char16_t (UTF-16)
Auto wchar_t (UTF-16) char16_t (UTF-16) char (UTF-8)

Make sure you know what representation your native representation expects when picking your charset.