2008-10-01 12 views
7

que tienen una función en un archivo DLL nativa se define de la siguiente manera:Mariscal clase de C++ "cadena" en C# P/Invoke

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

Me trataron de poner esto en P/Invoke interoperabilidad Asistente de Microsoft, pero se ahoga con la clase "string" (que creo que es de MFC?).

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

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

+0

Gran pregunta; Me sorprendió que no funcione automágicamente. http://msdn.microsoft.com/en-us/library/1b4az623.aspx –

+0

Me sorprendió demasiado ... no hay una razón importante por la que no debería ... pero parece que STL no va a funcionar con eso ... Además ... Simplemente cambiaría la función para usar WCHAR, pero no es una DLL que pueda cambiar. –

Respuesta

6

Parece que está intentando 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.

+0

Tenía miedo de eso ... cifras –

2

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 la siguiente

void SetPath(__in const WCHAR* path); 
0

Sí. Usted puede. En realidad, no solo std::string, std::wstring, cualquier clase estándar de C++ o sus propias clases se pueden calcular o instanciar y llamar 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, entonces podrá para 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 los detalles, consulte el siguiente enlace,

C#/.NET PInvoke Interop SDK

(yo soy el autor de la herramienta SDK)

vez que tenga el # clase de contenedor C de C++ clase preparada, es fácil implementar ICustomMarshaler para que pueda ordenar el objeto C++ de .NET.

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