2012-06-18 7 views
15

estoy usando una clase que tiene StringHandle campo que es un valor que representa una IntPtr LPCWSTR en C++.hacen IntPtr en C# .NET punto de valor de cadena

internal IntPtr StringHandle; // LPCWSTR 

decir ahora que tengo una cadena: string x = "abcdefg"

¿Cómo puedo utilizar el identificador de cadena para que apunte al principio de la cadena de modo que es como C++ LPCWSTR?

+0

¿Por qué quieres hacer eso? –

+0

Estoy trabajando con una interfaz que solo existe en el código nativo (C++) entonces estoy usando Interops desde .NET. sin embargo, la clase que tiene StringHandle no es mía y no quiero cambiarla. –

+6

Porque eso es lo que espera la biblioteca con la que está trabajando. No todo tiene un contenedor .NET creado para él, e incluso dentro del Framework, la clase Marshal puede obtener un buen uso cuando se trata de cosas como mensajes de Windows de bajo nivel. – KeithS

Respuesta

24

Debe copiar la cadena a la memoria no administrada primero y luego obtener el IntPtr desde esa ubicación. Puede hacerlo como:

IntPtr strPtr = Marshal.StringToHGlobalUni(x); 

Además, es necesario asegurarse de liberar la memoria no administrada:

Marshal.FreeHGlobal(strPtr); 

lo mejor es hacer todo esto en un try/finally.

+0

Realmente necesitaba este Marshal.StringToCoTaskMemUni ya que estoy usando COM pero gracias –

7

Cadenas administradas mueva en memoria cuando el recolector de basura compacta el montón. Por lo tanto, no tienen una dirección estable y no pueden enviarse directamente a un LPCWSTR. Necesitarás fijar la cadena con GCHandle.Alloc() para usar GCHandle.AddrOfPinnedObject o copiarlo en la memoria no administrada con Marshal.StringToHGlobalUni().

Se recomienda preferiblemente copiar si la dirección necesita ser estable por un tiempo.

+0

¿'AddrOfPinnedObject' en una' cadena' le da un puntero a los datos del caracter ('LPCWSTR' como se menciona en la pregunta)? (Según http://www.drdobbs.com/pinning-in-managed-c/184403869: sí) –