2011-11-14 15 views
5

Estoy tratando de encontrar una solución sobre cómo puedo pasar una matriz de matrices desde C# a una función nativa. Ya tengo un delegado para la función (Marshal.GetDelegateForFunctionPointer), pero ahora estoy tratando de pasar una matriz multidimensional (o más bien, una matriz de matrices) en ella.Reparando una matriz de matriz en C# (código inseguro)

Este ejemplo de código funciona cuando la entrada tiene 2 sub-arrays, pero necesito poder manejar cualquier cantidad de sub-arrays. ¿Cuál es la manera más fácil que se te ocurre para hacer eso? Yo prefiero no para copiar los datos entre matrices como este que va a ocurrir en un bucle en tiempo real (estoy comunicando con un efecto de audio)

public void process(float[][] input) 
{ 
    unsafe 
    { 
     // If I know how many sub-arrays I have I can just fix them like this... but I need to handle n-many arrays 
     fixed (float* inp0 = input[0], inp1 = input[1]) 
     { 
      // Create the pointer array and put the pointers to input[0] and input[1] into it 
      float*[] inputArray = new float*[2]; 
      inputArray[0] = inp0; 
      inputArray[1] = inp1; 
      fixed(float** inputPtr = inputArray) 
      { 
       // C function signature is someFuction(float** input, int numberOfChannels, int length) 
       functionDelegate(inputPtr, 2, input[0].length); 
      } 
     } 
    } 
} 

Respuesta

11

Puede fijar un objeto en su lugar sin usar fixed obteniendo en su lugar un pin GCHandle para el objeto en cuestión. Por supuesto, no hace falta decir que , al hacerlo, asumes la responsabilidad de garantizar que el puntero no sobreviva más allá del punto donde el objeto se desancla. Lo llamamos código "inseguro" por una razón; usted debe ser responsable de la administración segura de la memoria, no del tiempo de ejecución.

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

+0

Había leído sobre la clase GCHandle. Después de leer su respuesta intenté implementarla para mi llamada y parece estar funcionando bastante bien. Gracias por una respuesta rápida. – Valdemar

0

No tiene sentido tratar de bloquear el conjunto de referencias a las matrices administradas

Los valores de referencias probablemente no apunten a la dirección del primer elemento, e incluso si lo hicieran, eso sería un detalle de implementación. Podría cambiar de una versión a otra.

La copia de una serie de punteros a una gran cantidad de datos no debe ser tan lenta, especialmente no en comparación con el procesamiento multimedia al que está llamando.

Si es significativo, asigne sus datos fuera del montón administrado, entonces no hay fijación ni copia. Pero más contabilidad.

0

La manera más fácil de lo que se es utilizar una matriz de dimensión. Reduce la complejidad, la fragmentación de la memoria y también tendrá un mejor rendimiento. De hecho, lo hago en mi proyecto. Puede usar la indexación manual como array[i][j] = oneDimArray[i *n + j] y pasar n como parámetro a una función. Y que va a hacer sólo una fijación al igual que lo hecho en tu ejemplo:

public void process(float[] oneDimInput, int numberOfColumns) 
{ 
    unsafe 
    { 
     fixed (float* inputPtr = &oneDimInput[0]) 
     { 
       // C function signature is someFuction(
       // float* input, 
       // int number of columns in oneDimInput 
       // int numberOfChannels, 
       // int length) 
       functionDelegate(inputPtr, numberOfColumns, 2, oneDimInput[0].length); 
     } 
    } 
} 

También tengo que tener en cuenta, que los arrays de dos dimensiones rara vez se utilizan en las bibliotecas de computación de alto rendimiento como Intel MKL, Intel IPP y muchos otros. Incluso las interfaces BLAS y Lapack contienen solo matrices de una dimensión y emulan dos dimensiones con un enfoque que he mencionado (por razones de rendimiento).

+0

Esto no responde la pregunta. Es probable que el póster no pueda cambiar la firma de la función nativa. – Odrade

+0

Responde si puede, y es realmente la manera más fácil en ese caso. No hay información en la respuesta original si puede o no. –

+0

De hecho, puedo cambiar la firma, y ​​esta respuesta me llevó a considerar si la firma de la función es la mejor manera de hacerlo. Aunque no responde la pregunta que hice, me ayudó de alguna manera. – Valdemar