2010-07-13 2 views
12

domanda semplice, importare una funzione DLL e il parametro sono int *. Quando provo ad inserire Method (0), viene visualizzato un errore che dice: "int e int * non può convertire".DotNet - Che cosa è int *?

Che cosa significa?

risposta

15

Questa è la notazione C classica per un pointer to an int. Ogni volta che un tipo è seguito da un *, indica quel tipo come pointer per quel tipo. In C#, a differenza di C, è necessario definire esplicitamente funzioni come unsafe per utilizzare i puntatori, oltre a abilitare il codice unsafe nelle proprietà del progetto. Anche un tipo di puntatore non è direttamente intercambiabile con un tipo concreto, quindi il riferimento di un tipo deve essere preso per primo. Per ottenere un puntatore a un altro tipo, ad esempio un int, in C# (o C & C++), è necessario utilizzare l'operatore di dereferenza & (e commerciale) davanti alla variabile a cui si desidera ottenere un puntatore:

unsafe 
{ 
    int i = 5; 
    int* p = &i; 
    // Invoke with pointer to i 
    Method(p); 
} 

codice 'non sicuro' C#

seguito sono riportati alcuni articoli chiave su codice non sicuro e l'uso di puntatori in C#.

+0

Per aggiungere qui, '&' è ottenere il puntatore (indirizzo) di' int i' ... – Nate

+0

@Nate: buon punto, aggiungerò una spiegazione migliore dell'operatore di dereferenziazione. – jrista

+0

Stesso commento qui: non ha nulla a che fare con il codice non sicuro. L'argomento è semplicemente passato per riferimento. La parola chiave "ref" in C#. È anche un puntatore in C# nel momento in cui il compilatore JIT ha finito. –

6

È un pointer to an int. Generalmente meglio evitato nel codice gestito. È possibile che si desideri pubblicare la dichiarazione del metodo importata. Un IntPtr è di solito sufficiente per questo tipo di interoperabilità.

+1

È solo un argomento passato per riferimento. È ben supportato dal marshaller P/Invoke, l'utilizzo di IntPtr è un errore. –

+2

Dipende da cosa fa. Se è un array, 'int []' è quello che vuoi. Se è un handle, 'IntPtr' di solito è il migliore, specialmente se si pianifica di passare 0. Se si desidera un riferimento effettivo a un int,' ref int' o 'out int' potrebbe funzionare meglio. – Blindy

+1

Senza vedere la dichiarazione del metodo non sarei in grado di indovinare in un modo o nell'altro (ref vs array vs pointer). @Blindy ha ragione sui soldi. Dipende dal metodo che viene chiamato. Il LPARAM di SendMessage, per esempio, è solitamente configurato come IntPtr e quel tipo in genere possiede un puntatore di memoria (che può essere espresso come int *) – dkackman

2

Dipende dalla lingua utilizzata. In C#, dovresti dichiarare l'argomento con la parola chiave "ref". In VB.NET dovresti usare la parola chiave ByRef. E devi chiamarlo passando una variabile, non una costante. Qualcosa del genere:

int retval = 0; 
Method(ref retval); 
// Do something with retval 
//... 
+0

È praticamente uguale al & usato nella risposta accettata? –

+0

Sotto il cappuccio dopo che il jitter è finito, sì. –

+0

Se gli autori della DLL che ha usato decidono il metodo di firma # C# (int * p) ', allora non può invocare il metodo con la sintassi' Metodo (ref retval); 'proponi, giusto? Gli autori della DLL _could_ hanno scelto invece un metodo 'Method (ref int p)', ma per qualche motivo non l'hanno fatto. C# non offre "aritmetica" su variabili di tipo "ref int", come l'incremento per l'indirizzo "next", il modo in cui funziona con i puntatori "int * p" (come C# "p ++" e altri "non sicuri") . –