Search code examples
c#.netinteroppinvokeoptional-parameters

How to pass a nullable type to a P/invoked function


I have a few p/invoked functions (but I'm rewriting my code at the moment so I'm tidying up) and I want to know how to use/pass a nullable type as one of the parameters. working with int types isn't a problem but given the following:

[DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
    static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, int? enumerator, IntPtr hwndParent, uint Flags);

I'd like to be able to pass the Guid parameter as a nullable type. As it stands at the moment I can call it as:

SetupDiGetClassDevs(ref tGuid, null, IntPtr.Zero, (uint)SetupDiFlags.DIGCF_PRESENT );

but I need the first parameter to also be passable as null.


Solution

  • It's not possible to pass a Nullable type into a PInvoke'd function without some ... interesting byte manipulation in native code that is almost certainly not what you want.

    If you need the ability to pass a struct value as NULL to native code declare an overload of your PInvoke declaration which takes an IntPtr in the place of the struct and pass IntPtr.Zero

    [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, ref int enumerator, IntPtr hwndParent, uint Flags);
    [DllImport("setupapi.dll", CharSet = CharSet.Auto, SetLastError = true)]
        static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid, IntPtr enumerator, IntPtr hwndParent, uint Flags);
    

    Note: I added a ref class to the first signature. If the native signature can take NULL, it is likely a pointer type. Hence you must pass value types by reference.

    Now you can make calls like the following

    if (enumerator.HasValue) { 
      SetupDiGetClassDevs(someGuid, ref enumerator.Value, hwnd, flags);
    } else {
      SetupDiGetClassDevs(someGuid, IntPtr.Zero, hwnd, flags);
    }