Charsets and marshalling
Note
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.