2009-06-26 10 views
11

Mam kilka funkcji p/wywoływanych (ale przepisuję kod w tym momencie, więc sprzątam) i chcę wiedzieć, jak używać/przekazać typ zerowy jako jeden z parametrów. pracy z typów int nie jest problemem, ale biorąc pod uwagę, co następuje:Jak przekazać typ z możliwością zerowania do funkcji P/wywoływanej

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

Chciałbym, aby móc przekazać parametr Guid jako rodzaj pustych. Jak to stoi w tej chwili mogę nazwać jak:

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

ale muszę pierwszy parametr być również zadowalający jak null.

+1

@River kopalni nie jest kwestia wykraczająca ponieważ został poproszony w drodze powrotnej w 2009 roku;) –

+0

nowy jest próbą stworzenia kanoniczną wersję tego problem, z więcej rozwiązań, które są bardziej ogólne. – River

Odpowiedz

11

Nie można przekazać typu Nullable do funkcji PInvoke bez funkcji ... interesującej manipulacji bajtami w natywnym kodzie, która prawie na pewno nie jest tym, czego potrzebujesz.

Jeśli potrzebujesz zdolność przechodzenia struct jako wartość NULL do kodu natywnego zadeklarować przeciążenie swojej deklaracji pinvoke który bierze IntPtr w miejscu struktury i przekazać 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); 

Uwaga: Dodałem klasę ref do pierwszego podpisu. Jeśli macierzysty podpis może mieć wartość NULL, najprawdopodobniej jest to typ wskaźnika. Dlatego musisz przekazywać typy wartości przez odniesienie.

Teraz można wykonywać połączenia, jak na poniższym

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

Do tej pory przeciążałem moje funkcje P/invoke. Moje pytanie brzmiało, czy mogę to skrócić i uporządkować mój kod, nie wymagając przeciążania. Do tej pory udało mi się przekazać int (parametr 2) jako wartość zerową bez żadnych problemów, co oznacza, że ​​to ograniczenie dotyczy tylko typów strukturalnych? Inną rzeczą w jednym wcieleniu mojego kodu Zdefiniowałem parametr 2 jako '[MarshalAs (UnmanagedType.LPTStr)] Enumerator string ', który również pozwala mi unieważnić ten parametr podczas używania. –

+0

Moje przeprosiny ... Nie mogę uciec z nullable int :) –