Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PInvoke with a void * versus a struct with an IntPtr

Imagine I have a function called

Myfunction(const void * x);

My C# declaration could be

MyFunction(IntPtr x);

Is this functionally and technically equivalent to

struct MyStruct { IntPtr P; }

MyFunction(MyStruct x);

Or will there be a difference in how they are marshalled.

I'm asking this because the library I'm calling is all void *, typedef'd to other names, and in C# I'd like to get type safety, for what it's worth.

like image 227
halivingston Avatar asked Feb 12 '15 00:02

halivingston


1 Answers

If your StructLayout is Sequential, then it is indeed identical.

Easiest way to verify this for yourself is to try it out, of course:

Make a C++ Win32 DLL project:

extern "C"
{
    __declspec(dllexport) void MyFunction(const void* ptr)
    {
       // put a breakpoint and inspect
    }
}

Make a C# project:

    public struct Foo
    {
        public IntPtr x;
    }

    [DllImport(@"Win32Project1.dll", EntryPoint = "MyFunction", CallingConvention = CallingConvention.Cdecl)]
    public static extern void MyFunctionWithIntPtr(IntPtr x);

    [DllImport(@"Win32Project1.dll", EntryPoint = "MyFunction", CallingConvention = CallingConvention.Cdecl)]
    public static extern void MyFunctionWithStruct(Foo x);

    static void Main(string[] args)
    {
        IntPtr j = new IntPtr(10);
        var s = new Foo();
        s.x = new IntPtr(10);
        MyFunctionWithIntPtr(j);
        MyFunctionWithStruct(s);
    }

In your debug settings, make sure you select Native debugging is enabled.

You'll see both values to be 0xA.

Note, however, if you use out/ref parameters for your IntPtr vs Struct, they will be different values.

like image 86
mjsabby Avatar answered Oct 25 '22 16:10

mjsabby