Assume this C function:
void do_something(const char* str)
It stores the string somewhere for later reference.
Furthermore, I have this signature in C# to call this function:
[DllImport("NativeLib")]
static extern void do_something(string str);
Now, what do I need to do when passing a string to this method:
GCHandle.Alloc()
) (or is the marshaller creating a copy)?GCHandle.Alloc()
)? Or do I need to pass the return value of GCHandle.AddrOfPinnedObject()
?string
the correct data type (for do_something
) in this case? Or should I use IntPtr
instead?Storing pointers through an interop boundary is a Really Bad Idea, do everything you can to modify the C code to make a copy of the string instead.
Pinning the string as suggested in the upvoted answer isn't going to work, the pinvoke marshaller must convert the string to char* and releases that converted string after making the native call, invalidating the pointer. You must marshal the string yourself. Declare the argument as IntPtr and use Marshal.StringToHGlobalAnsi() to create the pointer value.
Or use Marshal.StringToCoTaskMemAnsi(), it allocates from the COM heap. Which is your real problem, there is no great scenario to release the string. The C code cannot release the string because it doesn't know how it was allocated. Your C# code cannot release the string because it doesn't know when the C code is done with the pointer. This is why copying the string is so important. You can live with the memory leak if you make this call only a few times.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With