String marshalling
Learn to pass managed strings to native APIs.
String marshalling
To pass a string to a native API you specify the marshal type: [DllImport("x.dll", CharSet = CharSet.Ansi)] for ANSI, CharSet.Unicode for UTF-16, CharSet.Auto for platform default.
You can also convert a single parameter with [MarshalAs(UnmanagedType.LPStr)]. The right type must match the encoding the function expects; otherwise the data is corrupted and the output becomes unreadable.
StringBuilder for out parameters
When a native function writes a string back (e.g. GetWindowText), you use StringBuilder. [DllImport("user32.dll")] static extern int GetWindowText(IntPtr h, StringBuilder s, int max); pre-allocates the buffer and marshals it on return.
Setting StringBuilder capacity is mandatory; otherwise the result is truncated. This is the standard way to talk to fixed-length C buffers.
Exercise Call puts with a CharSet
Declare [DllImport("libc.so.6", CharSet = CharSet.Ansi)] static extern int puts(string s);. In Main call puts("Hello"); and then write Console.WriteLine("Done");.
Show example solution
puts("Hello"); Console.WriteLine("Done");
Example solution:
using System;
using System.Runtime.InteropServices;
class Program
{
[DllImport("libc.so.6", CharSet = CharSet.Ansi)]
static extern int puts(string s);
static void Main()
{
puts("Hello");
Console.WriteLine("Done");
}
}
Test yourself
-
Match the CharSet types
- CharSet.Ansi
- ANSI (1 byte)
- CharSet.Unicode
- UTF-16
- CharSet.Auto
- Platform default
- UnmanagedType.LPStr
- ANSI string pointer
-
Which CharSet uses UTF-16 strings?
- CharSet.Unicode
- CharSet.None
- CharSet.Auto
- CharSet.Ansi
Show answer
CharSet.Unicode — Correct. CharSet.Unicode uses UTF-16.
-
Specify the CharSet
[DllImport("x.dll", ____ = CharSet.Unicode)] static extern void Greet(string s);Show answer
[DllImport("x.dll", CharSet = CharSet.Unicode)] static extern void Greet(string s);