2013-08-07 19 views
6

Sto provando a scrivere un wrapper attorno a un C function che si aspetta un puntatore a funzione e dati utente arbitrari (void*). Il puntatore alla funzione ho capito come gestire l'utilizzo dei delegati, ma non riesco a capire come convertire un object in un void*.Converti oggetto in vuoto * e ritorno?

posso farne una ref object, invece, dal momento che si comporta come un puntatore per quanto ne so, ma quando provo che ricevo un'eccezione come

una variante non valido è stato rilevato nel corso di una conversione da una variante non gestito a un oggetto gestito. Il passaggio di VARIANT non validi al CLR può causare eccezioni impreviste, danneggiamento o perdita di dati.

This "solution" potrebbe lavorare per me, ma ho pensato che ci deve essere un modo per passare dati arbitrari ad un C DLL in modo che possa essere passato torna più tardi?

+1

e IntPtr? –

+0

Personalmente, penso che farei meglio ad usare un puntatore a una 'struct' tramite un blocco' fixed' ... –

+0

@NoIdeaForName: La DLL C avrà un 'IntPtr' nessun problema, ma come faccio a girarlo ritorna in un 'oggetto' quando ritorna (e anche come fa 'lanciare' un oggetto su un IntPtr)? – mpen

risposta

2

Personalmente, consiglierei di utilizzare un struct qui, che è molto più applicabile per ciò che si sta tentando di fare (in più è possibile modificare il layout interno se necessario). Ad esempio, con un struct Foo, e un campo su un riferimento di tipofoo:

unsafe void Bar() 
{ 
    fixed (Foo* ptr = &foo) // here foo is a field on a reference-type 
    { 
     void* v = ptr; // if you want void* 
     IntPtr i = new IntPtr(ptr); // if you want IntPtr 
     // use v or i here... 
    } 
} 

Nota: se foo è una variabile locale, allora è in pila e non è nemmeno necessario essere fixed:

unsafe void Bar() 
{ 
    Foo foo = new Foo(); 
    Foo* ptr = &foo; // here foo is a local variable 

    void* v = ptr; // if you want void* 
    IntPtr i = new IntPtr(ptr); // if you want IntPtr 
    // use v or i here... 
} 
+0

Una domanda sul secondo bit - se 'foo' è in pila, non verrà estratto dallo stack alla fine di la funzione, lasciando così la DLL C con un puntatore pendente? – mpen

2

Se non sbaglio credo che avete bisogno Pointer.Box e Pointer.UnBox metodi. Questi metodi aiutano a inscatolare e a rimuovere il puntatore non gestito. Check out Pointer.Box e Pointer.UnBox in msdn.

+0

Se sto leggendo bene, questo suona all'indietro. 'Box' si aspetta un" puntatore di memoria non gestito fornito ". La DLL C * non * mi ha fornito un 'void *', ho bisogno di generarne uno per passarlo. E sono abbastanza sicuro che "Unbox" fallirà a meno che l'oggetto non sia stato inserito per primo. – mpen

+0

+1 Wow! Non sapevo di 'Pointer.Box'! – xanatos

+0

qual è il tipo effettivo di 'userdata' che vuoi passare? –