2010-10-04 13 views
7

Devo chiamare una funzione da un C api contenuto in una DLL. prototipo di funzione appare come segue ....Come marshall void * con piattaforma invocata

int func(char* name, void* value); 

in cui il contenuto del valore del puntatore possono riferirsi a qualsiasi tipo dipendente dal nome passato. Non sono sicuro di come configurare Dll inport per eseguire correttamente questo vuoto *. Ihave stato sperimentando IntPtr che sembra funzionare whe il valore è un int, ma non riesco a recuperare i valori correttamente per carri ecc

Sto cercando di importare la funzione come questa ...

[DllImport("dllname.dll", CharSet = CharSet.Ansi)] 
public static extern int func(string name, ref IntPtr value); 

nota dei pls quel valore è un risultato. Un puntatore a un valore di qualsiasi tipo, ovvero l'indirizzo in una regione globale di memoria di un valore di un tipo noto (noto al chiamante). In un c prog, il chiamante dovrebbe quindi trasmettere questo vuoto * al tipo desiderato e alla dereferenziazione per ottenere il valore effettivo memorizzato in tale posizione. Le risposte date finora sembrano basarsi sul presupposto che la funzione scriverà il risultato alla posizione del puntatore passata. La mia colpa non è stata troppo specifica. Scusate. C# non è la mia borsa, e io non so nemmeno se IntPtr è il modo di andare qui ...

risposta

2

Non è necessario il ref - IntPtr è il modo per passare void* in codice nativo.

[DllImport("dllname.dll", CharSet = CharSet.Ansi)] 
public static extern int func(string name, IntPtr value); 

EDIT: Il codice C può utilizzare l'ingresso di scrivere nella memoria richiesta. Il problema da affrontare è che il codice gestito sappia quanta memoria allocare per ogni tipo di valore restituito. Quindi è possibile allocare un blocco di dimensioni appropriate utilizzando Marshal.AllocHGlobal o Marshal.AllocCoTaskMem, liberato (in base al metodo di allocazione utilizzato) tramite FreeHGlobal o FreeCoTaskMem, una volta che il codice gestito viene eseguito con il valore di uscita.

Vedere la risposta di @Alex Farber per un esempio.

+0

Sarei dovuto essere più specifico scusa. Il valore IntPtr è un output. Nel caso di questa funzione sarà un puntatore a un valore che può essere di qualsiasi tipo. Ci si aspetta che il chiamante conosca il tipo che stanno cercando di recuperare. – matt

+0

@matt - la risposta è sempre la stessa - vedi modifica. –

+0

@matt - dai un'occhiata alla risposta e ai commenti di Hans - questa è la soluzione migliore. –

10

Il modo migliore per affrontare questo è fornire sovraccarichi della funzione in modo che tutto sia perfettamente pulito sul lato C#. Come questo:

[DllImport("dllname.dll", CharSet = CharSet.Ansi)] 
public static extern int func(string name, out int value); 
[DllImport("dllname.dll", CharSet = CharSet.Ansi)] 
public static extern int func(string name, out float value); 
// etc, one each for each type 
+0

concordato, a condizione che il codice C possa essere modificato questa è la soluzione migliore. –

+0

@Steve: nessuna modifica del codice C è necessaria. Vede solo il puntatore che passa il marshaller pinvoke. –

+0

allora questa è la soluzione migliore e il +1 è ancora più meritato –

2
 
[DllImport("dllname.dll", CharSet = CharSet.Ansi)] 
public static extern int func(string name, IntPtr value); 

... 

// n - number of bytes which is enough to keep any type used by function 
IntPtr ptr = Marshal.AllocHGlobal(n); 
func(name, ptr); 

// Use Marshal.ReadByte, Marshal.ReadInt32 ... or Marshal.Copy 
// to copy from ptr filled by func to managed variable. For example: 
byte b = Marshal.ReadByte(ptr); 

Marshal.FreeHGlobal(IntPtr); 
0

A volte, potrebbe essere più facile da usare questo approccio.

Dichiarazione:

[DllImport("dllname.dll", CharSet = CharSet.Ansi)] 
public static extern int func([MarshalAs(UnmanagedType.LPTStr)] string name, [MarshalAs(UnmanagedType.AsAny)] object value); 

utilizzo Esempio passare un valore:

func("some string", (int)12); 
func("some string", (double)12); 

Esempio dell'uso di passare una stringa:

func("some string", "test"); 

utilizzo Esempio passare una variabile:

int value = 12; 
func("some string", value); 
Problemi correlati