3

I have struct which is defined in Win32 DLL like the following:

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

And there is a function:

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

How can I capture the return value of this function If I'm using P/Invoke from a C# Application

6
  • 1
    That looks like C more than C++. Commented Sep 24, 2012 at 8:36
  • I would think double** translates to double[][]. Not sure if you have to decorate it with an attribute though to get it to work right. Commented Sep 24, 2012 at 8:37
  • @lc. You need to marshal it manually Commented Sep 24, 2012 at 12:25
  • You declare data to be double** but actually it is int**. Fix that and the technique of @user629926's answer will get you home. Commented Sep 24, 2012 at 12:37
  • You first malloc is wrong. It should be mat.data = (int**) malloc (sizeof(int*) * mat.m) but better would be (int**) malloc(sizeof(*mat.data)*mat.m) Commented Sep 24, 2012 at 12:39

2 Answers 2

5

I am not sure if it works, but from memory: Declare data as IntPtr and use this :

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;
}
Sign up to request clarification or add additional context in comments.

14 Comments

The 'new double[]' would be in managed memory. And double arrays in C# are objects with different layout. Unfortunately, your approach won't work.
Sorry if someone can format my answer,my mobile editor wont format it right. If he wants double[,] instead of double[][] I can edit the question?
It's better, but the problem is still with the 2D-ness of the array. The zig-zag array you propose won't map the '**' pointer.
I just asumed that by double** he wanted array of double arrays.
What do you mean by free. If you wish to free memory alocated by struct from c# . You should make your own free routine ,export it and call lt from c#.
|
1

The answer is short but disappointing: you have to convert the multidimensional array to the single-dimensional one.

There is an answer using AllocHGlobal: Pass multi - dimensional array from managed code to unmanaged code

This solution does similar thing, but in the C# definition in your case you have to make the data field to be of IntPtr type and in unmanaged code you have to assume it is a single-dimensional array.

There is another solution using Marshal.UnsafeAddrOfPinnedArrayElement (MSDN and StackOverflow), but it still assumes you are using the one-dimensional arrays.

Better options would follow if you tell what is the problem you are trying to solve. Is it a pure return-from-one-very-important-function-and-forget-this-PInvoke or are you trying to do a constant bidirectional marshalling ?

1 Comment

You certainly do not need to convert to single dimensional

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.