2009-06-28 12 views
8

Necesito su ayuda con el siguiente escenario:¿Cómo puedo pasar datos MemoryStream a no administrado C++ DLL utilizando P/Invoke

estoy leyendo algunos datos de hardware en un MemoryStream (C#) y que necesita para pasar estos datos en memoria a un dll implementado en C++ no administrado (usando el puntero ??). Los datos leídos (en la corriente) es muy grande (megabytes). Entiendo que puedo P/Invoke esta DLL pero lo que no estoy seguro es cómo pasar el puntero del/de referencia de los datos de la secuencia a la API de C++?

Debo admitir que estoy confundido ya que soy nuevo en C# - ¿Debo usar inseguro/fijo ya que los datos son grandes o son irrelevantes ya que el objeto MemoryStream es administrado por GC? Algún ejemplo de código/descripción detallada sería muy útil. Gracias

Firma del API no administrada:

BOOL doSomething (void * rawData, int dataLength)

+0

¿Qué tipo de datos requiere el C++ dll? – scottm

+0

Requiere datos sin procesar - byte/void *. Puedo cambiar la API dll según sea necesario. –

Respuesta

12

si es sólo esperando bytes se puede leer MemoryStream en una matriz de bytes y luego pasar un puntero a que a el método.

Usted tiene que declarar el método externo:

[DllImport("mylibrary.dll", CharSet = CharSet.Auto)] 
public static extern bool doSomething(IntPtr rawData, int dataLength); 

A continuación, lea los bytes desde MemoryStream en una matriz de bytes. Asignar un GCHandle cuales:

Una vez asignado, se puede utilizar un GCHandle para evitar que el objeto gestionado de siendo recogida por la basura colector cuando un cliente no administrado tiene la única referencia. Sin tal un mango, el objeto puede ser recogida por el recolector de basura antes de completar su trabajo en nombre del cliente no administrado .

Y, por último, utilice el método AddrOfPinnedObject para obtener un IntPtr para pasar al dll de C++.

private void CallTheMethod(MemoryStream memStream) 
{ 
    byte[] rawData = new byte[memStream.Length]; 
    memStream.Read(rawData, 0, memStream.Length); 

    GCHandle rawDataHandle = GCHandle.Alloc(rawData, GCHandleType.Pinned); 
    IntPtr address = handle.AddrOfPinnedObject(); 

    doSomething(address, rawData.Length); 
    rawDataHandle.Free(); 
} 
+0

Gracias. Sí, este método básicamente es para compresión, por lo que requerirá/operará en los datos sin procesar que se le pasen. También curiosidad datos marcados insegura se coloca en el montón o pila en C#? –

+0

Es lo mismo que para el código no marcado como inseguro. – scottm

+0

Solo para aclarar, este código no se considera inseguro. – scottm

Cuestiones relacionadas