2012-06-18 6 views
15

Sto usando una classe che ha il campo StringHandle che è un valore IntPtr che rappresenta uno LPCWSTR in C++.rendere IntPtr in C# .NET al valore stringa

internal IntPtr StringHandle; // LPCWSTR 

dire ora che ho una stringa: string x = "abcdefg"

Come posso utilizzare la maniglia String per indicare l'inizio della stringa in modo che sia simile a C++ LPCWSTR?

+0

Perché vuoi farlo? –

+0

Sto lavorando con un'interfaccia che esiste solo nel codice nativo (C++), quindi sto usando Interops da .NET. tuttavia, la classe che ha StringHandle non è mia e non voglio cambiare. –

+6

Perché è quello che la biblioteca con cui sta lavorando si aspetta. Non tutto ha un wrapper .NET creato per questo, e anche all'interno del Framework la classe Marshal può essere utile quando si ha a che fare con messaggi di Windows di basso livello. – KeithS

risposta

24

È necessario copiare la stringa alla memoria non gestita prima e quindi ottenere il IntPtr da quella posizione. Si può fare in modo simile:

IntPtr strPtr = Marshal.StringToHGlobalUni(x); 

Inoltre, è necessario fare in modo di liberare la memoria non gestita:

Marshal.FreeHGlobal(strPtr); 

è meglio fare tutto questo in un try/finally.

+0

Avevo davvero bisogno di questo Marshal.StringToCoTaskMemUni poiché sto usando COM ma grazie –

7

Stringhe gestite spostare nella memoria quando il garbage collector compatta l'heap. Quindi non hanno un indirizzo stabile e non possono essere espressi direttamente su un LPCWSTR. Dovrai pin la stringa con GCHandle.Alloc() per usare GCHandle.AddrOfPinnedObject o copiarlo nella memoria non gestita con Marshal.StringToHGlobalUni().

Preferisco fortemente copiare se l'indirizzo deve essere stabile per un po '.

+0

Does'AddrOfPinnedObject' su una 'stringa' ti fornisce un puntatore ai dati dei caratteri (' LPCWSTR' come menzionato nella domanda)? (Secondo http://www.drdobbs.com/pinning-in-managed-c/184403869: Sì) –