Is it valid to use unsafe struct * as an opaque type instead of IntPtr in .NET Platform Invoke?
- by David Jeske
.NET Platform Invoke advocates declaring pointer types as IntPtr. For example, the following
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);
However, I find when interfacing with interesting native interfaces, that have many pointer types, flattening everything into IntPtr makes the code very hard to read and removes the typical typechecking that a compiler can do.
I've been using a pattern where I declare an unsafe struct to be an opaque pointer type. I can store this pointer type in a managed object, and the compiler can typecheck it form me. For example:
class Foo {
unsafe struct FOO {}; // opaque type
unsafe FOO *my_foo;
class if {
[DllImport("mydll")]
extern static unsafe FOO* get_foo();
[DllImport("mydll")]
extern static unsafe void do_something_foo(FOO *foo);
}
public unsafe Foo() {
this.my_foo = if.get_foo();
}
public unsafe do_something_foo() {
if.do_something_foo(this.my_foo);
}
While this example may not seem different than using IntPtr, when there are several pointer types moving between managed and native code, using these opaque pointer types for typechecking is a godsend.
I have not run into any trouble using this technique in practice. However, I also have not seen an examples of anyone using this technique, and I wonder why. Is there any reason that the above code is invalid in the eyes of the .NET runtime?
My main question is about how the .NET GC system treats "unsafe FOO *my_foo". Is this pointer something the GC system is going to try to trace, or is it simply going to ignore it? My hope is that because the underlying type is a struct, and it's declared unsafe, that the GC would ignore it. However, I don't know for sure. Thoughts?