.net c++ string interop marshalling

.net - Clase de "cuerda" Marshal C++ en C#P/Invoke



string interop (3)

El asistente de interoperabilidad de PInvoke solo es compatible con C, no con C ++. Desafortunadamente, la clase MFC String (¿Creo que CString?) Es C ++ y no funcionará a través del asistente. En su lugar, intente utilizar lo siguiente

void SetPath(__in const WCHAR* path);

Tengo una función en una DLL nativa definida de la siguiente manera:

#include <string> void SetPath(string path);

Traté de poner esto en el Asistente de interoperabilidad de P / Invoke de Microsoft, pero se atasca en la clase "cadena" (que creo que es de MFC?).

He intentado ordenarlo como una variedad de tipos diferentes (C # String, char [], byte []) pero cada vez que obtengo una NotSupportedException o una Excepción de ensamblaje nativa (dependiendo de qué clasificación intenté).

Como siempre, ¿alguien ha hecho Interoperabilidad nativa / administrada donde se usa la clase de cadena nativa? ¿Hay alguna forma de Marshal esto? ¿Tendré que escribir mi propio Marshaler?


Parece que estás tratando de usar la clase de cadena de biblioteca estándar de C ++. Dudo que sea fácil para Marshal. Mejor quedarse con un char * y Marshal como StringBuilder. Eso es lo que suelo hacer. Tendrá que agregar un contenedor que genere la cadena de C ++ por usted.


Sí. Usted puede. En realidad, no solo std::string , std::wstring , cualquier clase estándar de C ++ o sus propias clases pueden ser ordenadas o instanciadas y llamadas desde C # /. NET.

La idea básica de instanciar un objeto C ++ del mundo .NET es asignar el tamaño exacto del objeto C ++ de .NET, luego llamar al constructor que se exporta desde la DLL C ++ para inicializar el objeto, luego podrá llamar a cualquiera de las funciones para acceder a ese objeto C ++, si alguno de los métodos involucra otras clases de C ++, también deberá envolverlos en una clase C #, para los métodos con tipos primitivos, simplemente puede P / invocarlos. Si solo tiene unos pocos métodos para llamar, sería simple, la codificación manual no tomará mucho tiempo. Cuando haya terminado con el objeto C ++, llame al método destructor del objeto C ++, que también es una función de exportación. si no tiene uno, solo necesita liberar su memoria de .NET.

Aquí hay un ejemplo.

public class SampleClass : IDisposable { [DllImport("YourDll.dll", EntryPoint="ConstructorOfYourClass", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.ThisCall)] public extern static void SampleClassConstructor(IntPtr thisObject); [DllImport("YourDll.dll", EntryPoint="DoSomething", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.ThisCall)] public extern static void DoSomething(IntPtr thisObject); [DllImport("YourDll.dll", EntryPoint="DoSomethingElse", CharSet=CharSet.Ansi, CallingConvention=CallingConvention.ThisCall)] public extern static void DoSomething(IntPtr thisObject, int x); IntPtr ptr; public SampleClass(int sizeOfYourCppClass) { this.ptr = Marshal.AllocHGlobal(sizeOfYourCppClass); SampleClassConstructor(this.ptr); } public void DoSomething() { DoSomething(this.ptr); } public void DoSomethingElse(int x) { DoSomethingElse(this.ptr, x); } public void Dispose() { Marshal.FreeHGlobal(this.ptr); } }

Para más detalles, consulte el enlace a continuación,

C # /. NET PInvoke Interop SDK

(Soy el autor de la herramienta SDK)

Una vez que tenga lista la clase contenedora C # para su clase C ++, es fácil implementar ICustomMarshaler para que pueda ICustomMarshaler el objeto C ++ de .NET.

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.icustommarshaler.aspx