Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Platform Invoke, bool, and string

suppose a dll contains the following functions

extern "C" __declspec(dllexport) void f(bool x)
{
   //do something
}
extern "C" __declspec(dllexport) const char* g()
{
   //do something else
}

My first naive approach to use these functions from C# was as follows:

[DllImport("MyDll.dll")]
internal static extern void f(bool x);
[DllImport("MyDll.dll")]
internal static extern string g();

The first surprise was that C++ bool doesn't convert into C# bool (strange runtime behavior, but no crashes, though). So I had to change bool to byte and convert from one to another by hand. So, first question is, is there any better way to marshal bool (note that this is bool, not BOOL)

The second surprise was that the raw string returned by the dll function was OWNED by the C# string, not copied, as I would expect, and eventually the C# code frees the memory returned by the dll. I found this out because the program crashed, but then I changed the return type to sbyte* and manually initialized the string with that pointer which already does the copy. So the second question is: 2.1: Is there any better way to prevent the marshalled string from owning the pointer. 2.2: WTF?! Why does C# do that? I mean, an obvious case is when the dll func returns a literal, and C# tries to delete it...

Thanks in advance, and hopefully my questions aren't vague or incomprehensible.

like image 552
Armen Tsirunyan Avatar asked Oct 10 '10 20:10

Armen Tsirunyan


2 Answers

[DllImport("MyDll.dll")]
internal static extern void f( [MarshalAs(UnmanagedType.I1)] bool x );
[DllImport("MyDll.dll")]
[return: MarshalAs(UnmanagedType.LPStr)]
internal static extern string g();
like image 159
Vinzenz Avatar answered Nov 01 '22 11:11

Vinzenz


By default .NET marshals between C++ BOOL (4 bytes) and .NET bool type automatically. For the C++ bool (single byte) type you need to specify how to marshal:

[DllImport("MyDll.dll")]
internal static extern void f([MarshalAs(UnmanagedType.I1)] bool x);
like image 5
Darin Dimitrov Avatar answered Nov 01 '22 10:11

Darin Dimitrov