Pregunta

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

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

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

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

¿Como cualquier persona que haya hecho Interop nativa / administrada donde se usa la clase de cadena nativa? ¿Hay alguna manera de marchar esto? ¿Voy a tener que escribir mi propio Marshaler?

¿Fue útil?

Solución

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

Otros consejos

El asistente de interoperabilidad PInvoke solo admite C no C ++. Desafortunadamente, la clase de cadena MFC (CString, ¿creo?) Es C ++ y no funcionará a través del asistente. En su lugar, intente usar lo siguiente

void SetPath(__in const WCHAR* path);

Sí. Usted puede. En realidad, no solo std :: string , std :: wstring , cualquier clase de C ++ estándar o sus propias clases se pueden calcular y crear instancias y llamar desde C # / .NET.

La idea básica de crear una instancia de un objeto C ++ desde el mundo .NET es asignar el tamaño exacto del objeto C ++ desde .NET, luego llamar al constructor que se exporta desde la DLL de C ++ para inicializar el objeto, luego podrá llame a cualquiera de las funciones para acceder a ese objeto de C ++, si alguno de los métodos involucra otras clases de C ++, también tendrá que envolverlos en una clase de C #, para los métodos con tipos primitivos, simplemente puede P / Invocarlos. Si solo tiene algunos métodos para llamar, sería sencillo, 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 siguiente enlace,

C # /. NET PInvoke Interop SDK

(Soy el autor de la herramienta SDK)

Una vez que tenga preparada la clase de envoltorio de C # para su clase de C ++, es fácil implementar ICustomMarshaler para poder ordenar el objeto de C ++ desde .NET.

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top