2012-09-24 3 views
3

Je struct qui est défini dans Win32 DLL comme ce qui suit:PInvoke struct retour avec tableau à deux dimensions

typedef struct matrix 
{ 
    double** data; 
    int m; 
    int n; 
} Matrix; 

Et il y a une fonction:

Matrix getMatrix(void);

Matrix getMatrix() 
{ 
    Matrix mat; 

    mat.m = 2; 
    mat.n = 2; 

    mat.data = (double**) malloc (sizeof(double*) * 4); 

    mat.data[0] = (double*) malloc (sizeof(double) * 2); 
    mat.data[1] = (double*) malloc (sizeof(double) * 2); 

    mat.data [0][0]=1; 
    mat.data [0][1]=2; 
    mat.data [1][0]=3; 
    mat.data [1][1]=4; 

    return mat; 
} 

Comment puis-je capturer la valeur de retour de cette fonction? Si j'utilise P/Invoke à partir d'une application C#

+1

Cela ressemble à C plus C++. – juanchopanza

+0

Je pense que 'double **' se traduit par 'double [] []'. Vous ne savez pas si vous devez le décorer avec un attribut pour le faire fonctionner correctement. –

+0

@lc. Vous devez le marshaler manuellement –

Répondre

3

Je ne sais pas si cela fonctionne, mais de la mémoire: Déclarer les données IntPtr et utiliser ce :

static double[][] FromNative (IntPtr data, int m,int n) 
{ 
    var matrix=new double[m][]; 

    for(int i=0;i<m;i++) 
    { 
     matrix[i]=new double[n]; 
     Marshal.Copy(Marshal.ReadIntPtr(data),matrix[i],0,n); 
     data =(IntPtr)(data.ToInt64()+IntPtr.Size); 
    } 

    return matrix; 
} 
+0

Le 'nouveau double []' serait dans la mémoire gérée. Et les tableaux doubles en C# sont des objets avec une disposition différente. Malheureusement, votre approche ne fonctionnera pas. –

+0

Désolé si quelqu'un peut formater ma réponse, mon éditeur mobile ne le formatera pas correctement. S'il veut double [,] au lieu de double [] [] je peux éditer la question? – user629926

+0

C'est mieux, mais le problème est toujours avec le '2D-ness' du tableau. Le tableau zig-zag que vous proposez ne mappera pas le pointeur "**". –

1

La réponse est courte mais décevante: vous devez convertir le tableau multidimensionnel en tableau unidimensionnel.

Il y a une réponse à l'aide AllocHGlobal: Pass multi - dimensional array from managed code to unmanaged code

Cette solution fait même chose, mais dans le C# définition dans votre cas, vous devez rendre le champ data être de type IntPtr et code non managé vous devez assumer c'est un tableau unidimensionnel.

Il existe une autre solution utilisant Marshal.UnsafeAddrOfPinnedArrayElement (MSDN et StackOverflow), mais il suppose toujours que vous utilisez les tableaux unidimensionnels.

De meilleures options suivront si vous dites quel est le problème que vous essayez de résoudre. Est-ce un pur return-from-one-very-important-function-et-forget-this-PInvoke ou essayez-vous de faire un marshalling bidirectionnel constant?

+0

Vous n'avez certainement pas besoin de convertir en dimension unique –

Questions connexes