2011-11-14 6 views
5

Sto cercando di trovare una soluzione su come posso passare una matrice di array da C# a una funzione nativa. Ho già un delegato alla funzione (Marshal.GetDelegateForFunctionPointer), ma ora sto provando a passare una matrice multidimensionale (o meglio una matrice di matrici) in essa.Correzione di una matrice di array in C# (codice non sicuro)

Questo esempio di codice funziona quando l'input ha 2 sotto-array, ma devo essere in grado di gestire qualsiasi numero di sotto-array. Qual è il modo più semplice in cui puoi pensare di farlo? Preferirei non per copiare i dati tra gli array come questo accadrà in un loop in tempo reale (sto comunicando con un effetto 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); 
      } 
     } 
    } 
} 

risposta

11

È possibile bloccare un oggetto in posizione senza utilizzare fixed ottenendo invece un oggetto appuntato GCHandle nell'oggetto in questione. Ovviamente, dovrebbe essere ovvio che così facendo si assuma la responsabilità di assicurarsi che il puntatore non sopravviva oltre il punto in cui l'oggetto è sbloccato. Lo chiamiamo codice "non sicuro" per un motivo; si diventa responsabili della gestione sicura della memoria, non del runtime.

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

+0

Ho letto della classe GCHandle. Dopo aver letto la tua risposta, ho provato ad implementarlo per la mia chiamata e sembra che funzioni abbastanza bene. Grazie per una rapida risposta. – Valdemar

0

non ha senso cercare di bloccare la serie di riferimenti agli array gestiti.

I valori dei riferimenti in là probabilmente non puntano sull'indirizzo del primo elemento, e anche se lo fossero, sarebbe un dettaglio di implementazione. Potrebbe cambiare da versione a versione.

La copia di una serie di puntatori su molti dati non dovrebbe essere così lenta, soprattutto se paragonata all'elaborazione multimediale che si sta chiamando.

Se è significativo, allocare i dati al di fuori dell'heap gestito, quindi non è possibile aggiungere o copiare. Ma più contabilità.

0

Il modo più semplice che conosco è quello di utilizzare un array dimensione. Riduce la complessità, la frammentazione della memoria e avrà anche prestazioni migliori. Lo faccio davvero nel mio progetto. È possibile utilizzare l'indicizzazione manuale come array[i][j] = oneDimArray[i *n + j] e passare n come parametro a una funzione. E si farà un solo fissaggio, proprio come hai fatto nel tuo esempio:

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); 
     } 
    } 
} 

Inoltre ho bisogno di notare che due array di dimensioni raramente utilizzati nelle librerie di calcolo ad alte prestazioni come Intel MKL, Intel IPP e molti altri. Anche le interfacce BLAS e Lapack contengono solo un array di dimensioni ed emulano due dimensioni utilizzando l'avviso che ho menzionato (per motivi di prestazioni).

+0

Questo non risponde alla domanda. È probabile che il poster non possa modificare la firma della funzione nativa. – Odrade

+0

Risponde se può, ed è davvero il modo più semplice in questo caso. Non c'è nessuna informazione nella risposta originale se può o no. –

+0

In realtà posso modificare la firma e questa risposta mi ha indotto a considerare se la firma della funzione è il modo migliore per andare. Sebbene non risponda alla domanda che ho posto, mi ha aiutato in qualche modo. – Valdemar