Reputation: 8898
How do I marshal a .net string to a null terminated ascii or utf8 IntPtr. For use on linux when interloping to a c lib.
I'm trying to call a c function with signiture like the following:
void my_function(const char* str)
My c# definition is as follows:
[DllImport("mylib.so)]
public static extern void my_function(IntPtr str);
I'm using an IntPtr for the interop because the native code holds onto the string longer than the duration of the function call. So I need to be able to marshal/pin it myself.
Things I've considered:
There is also the option of converting to a ascii or utf8 byte array and then marshalling the resulting array (with a null terminator on the end) but this seem like overkill, especially if one of the string marshalling options does the correct thing.
Upvotes: 1
Views: 1855
Reputation: 244782
The correct solution is Marshal.StringToHGlobalAnsi
. This is the ANSI version of the Marshal.StringToHGlobalUni
function. The ANSI version deals with strings which use char
as the underlying character type, whereas the Unicode version deals with wide strings which use wchar_t
as the underlying character type. The function names were written with Win32-colored glasses.
From your perspective, you have an unmanaged C routine that expects a C-style string, using char
as the underlying character type, so that matches with Marshal.StringToHGlobalAnsi
.
Marshal.StringToHGlobalAnsi
allocates unmanaged memory for the string, which you can then pass to the C code. Because the memory is allocated on the unmanaged heap, GC pinning is not necessary. Once the C code is done, you will need to free the memory by calling Marshal.FreeHGlobal
.
Upvotes: 2