Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass multi - dimensional array from managed code to unmanaged code

I would like to do the following:

  1. Create three dimesinal array in c# code like this:

    var myArray = new short[x,y,z];
    UnanagedFunction(myArray);
    
  2. Pass it to unmanaged code (c++) like this:

    void UnmanagedFunction(short*** myArray)
    {
        short first = myArray[0][0][0];
    }
    

UPDATED When I try the following code I have runtime error:

Attempted to read or write to protected memory.

Thank you!!!

like image 662
Sergey Kucher Avatar asked Aug 22 '11 20:08

Sergey Kucher


2 Answers

IntPtr Array3DToIntPtr(short[, ,] Val)
        {
            IntPtr ret = Marshal.AllocHGlobal((Val.GetLength(0) + Val.GetLength(1) + Val.GetLength(2)) * sizeof(short));

            int offset = 0;
            for (int i = 0; i < Val.GetLength(0); i++)
            {

                for (int j = 0; j < Val.GetLength(1); j++)
                {
                    for (int k = 0; k < Val.GetLength(2); k++)
                    {
                        Marshal.WriteInt16(ret,offset, Val[i, j, k]);
                        offset += sizeof(short);


                    }
                }
            }

            return ret;
        }

This has been tested and it works, the only limitation is that you have to call Marshal.FreeHGlobal on the array pointer when you are done with it or you will get a memory leak, I would also suggest that you change your c++ function so that it accepts the array dimensions or you will only be able to use 3d arrays of specific size

like image 170
Djole Avatar answered Oct 20 '22 19:10

Djole


I'm writing it in pure C#, but if you take away the unsafe static from Func, the Func should work in C/C++. Be aware that I'm note sure sure it's ok ok to write this :-) I'm using this Indexing into arrays of arbitrary rank in C#

static unsafe void Main(string[] args) {
    var myArray = new short[5, 10, 20];

    short z = 0;

    for (int i = 0; i < myArray.GetLength(0); i++) {
        for (int j = 0; j < myArray.GetLength(1); j++) {
            for (int k = 0; k < myArray.GetLength(2); k++) {
                myArray[i, j, k] = z;
                z++;
            }
        }
    }

    // myArray[1, 2, 3] == 243

    fixed (short* ptr = myArray) {
        Func(ptr, myArray.GetLength(0), myArray.GetLength(1), myArray.GetLength(2));
    }
}

// To convert to C/C++ take away the static unsafe
static unsafe void Func(short* myArray, int size1, int size2, int size3) {
    int x = 1, y = 2, z = 3;
    int el = myArray[x * size2 * size3 + y * size3 + z]; // el == 243
}
like image 29
xanatos Avatar answered Oct 20 '22 18:10

xanatos