2009-06-26 7 views
11

Ho alcune funzioni p/invocate (ma sto riscrivendo il mio codice al momento in modo che sto riordinando) e voglio sapere come usare/passare un tipo nullable come uno dei parametri. lavorare con i tipi int non è un problema, ma dato il seguente:Come passare un tipo Null in una funzione P/invocato

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

mi piacerebbe essere in grado di passare il parametro Guid come un tipo nullable. Così com'è in questo momento posso chiamarlo come:

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

ma ho bisogno il primo parametro di essere anche passabile come null.

+1

@River La mia non è la questione incriminato in quanto questo è stato chiesto nel lontano 2009;) –

+0

quello nuovo è un tentativo di creare una versione canonica di questo problema, con più soluzioni che sono più generali. – River

risposta

11

Non è possibile passare un tipo Nullable in una funzione PInvoke senza alcune ... manipolazioni di byte interessanti nel codice nativo che non è quasi certamente ciò che si desidera.

Se è necessario la possibilità di passare un valore struct come NULL in codice nativo dichiarare un sovraccarico della vostra dichiarazione PInvoke che prende un IntPtr al posto di struct e passare 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); 

Nota: Ho aggiunto una classe ref alla prima firma. Se la firma nativa può assumere NULL, è probabile che sia un tipo di puntatore. Quindi devi passare i tipi di valore per riferimento.

Ora è possibile effettuare chiamate, come il seguente

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

Ho sovraccaricato le mie funzioni P/invoke finora. La mia domanda era di vedere se potevo scorciatoia e riordinare il mio codice non avendo più bisogno di sovraccaricare. Finora sono stato in grado di passare int (parametro 2) come valore nullable senza problemi vuol dire che questa restrizione si applica solo ai tipi strutturati? Un'altra cosa in una incarnazione del mio codice ho definito il parametro 2 come '[MarshalAs (UnmanagedType.LPTStr)] stringa Enumerator' che mi permette anche di annullare questo parametro durante l'uso. –

+0

Le mie scuse ... Non riesco a farla franca con un nullable int :) –