2

I'm working on a managed C++ wrapper for unmanaged C++ code and have a question. Just for simplicity let's say that I need to pass a 2D array from C# code to Managed C++ to Unmanaged C++. I have no problem with 1D array but stuck with 2D version. Converting it to 1D is the option, but I want to take a look if there are other ways.

For simplicity let say I want to send 2D array to unmanaged code using intermediate wrapper and change its values.

so here is C# code with a call to managed C++:

MNumeric wrapper = new MNumeric();  //managed C++ object
int[,] dArr = new int[10, 10];
for (int i = 0; i < 10; i++)
        {
            for (int j = 0; j < 10; j++)
            {
                dArr[i, j] = 10;
            }
        }
wrapper.ChangeArray(dArr, Convert.ToInt32(Math.Sqrt(dArr.Length)))

Managed C++:

void MNumeric::ChangeArray(cli::array<int,2> ^arr, int mySize)
{
      //some code to call Unmanaged C++ passing managed 2D array ???
}

Unmanaged C++

void UNumeric::ChangeArray(int** arr, int mySize)
{
    for(int i=0;i<mySize;i++)
    {
        for(int j=0;j<mySize;j++)
        {
            arr[i][j]=i;
        }
    }
}

Thanks a lot for your help.

Looks like I fix one error but got another. My C++ Managed code looks like this now.

void MNumeric::ChangeArray(cli::array<int,2> ^arr, int mySize)
{
    pin_ptr<int> p_arr = &arr[0,0];
    u_num->ChangeArray((int**)p_arr, mySize);           
}

where u_num is just a pointer to UNumeric class. The error I got now is the following:

Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

Any ideas appreciated.

ilyaw77
  • 937
  • 3
  • 10
  • 15

2 Answers2

3
void MNumeric::ChangeArray(cli::array&ltint,2> ^arr, int mySize) 
{
    pin_ptr&ltint> p = &arr[0,0];   // pin pointer to first element in arr
    int* np = p;   // pointer to the first element in arr
    UNumeric::ChangeArray((int**)np, mySize);
}
Alex F
  • 42,307
  • 41
  • 144
  • 212
  • Alex, thanks for reply, but this solution does not work. pin_ptr p = &arr[0][0] line throws error C3262: invalid array indexing: 1 dimension(s) specified for 2-dimensional 'cli::array ^' – ilyaw77 Jun 15 '11 at 16:07
  • Alex, I was able to fix this problem using pin_ptr p_arr = &arr[0,0]; because it is 2d array not jagged array. Code compiles fine now but when I'm trying to run I get AccessViolationException on u_num->ChangeArray((int**)np, mySize) line. – ilyaw77 Jun 15 '11 at 16:45
  • @lyaw77: Replace arr->Length with mySize in my answer. – Alex F Jun 15 '11 at 17:29
2

You should not use a cast here, it could hide potentially important warnings. Notably, a 2D array is not convertible to an int**. An int**, is a pointer to an array of pointers. An int*[] is a pointer to an array of arrays. You have a function that takes an array of pointers. It wants a managed int[][], not an int[,]. Your compiler would thoroughly have shouted at you for attempting this, if you hadn't casted.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • Thank you for the reply. I already tried to go this way but with the same error: in C# I had: int[][] dArr = new int[10][]; in Managed C++: void MNumeric::ChangeArray(cli::array^>^ arr, int mySize){pin_ptr p_arr = &arr[0][0];u_num->ChangeArray((int**)p_arr, mySize);}, and I still have the same error. – ilyaw77 Jun 15 '11 at 20:30
  • @ilyaw77: That's because you never allocated the second lot of arrays. You allocated an array of pointers and then never set those pointers to point anywhere. Oh, and *take out the cast*. – Puppy Jun 16 '11 at 10:05
  • Thank you for advice, I was able to do it using GCHandle class. – ilyaw77 Jun 16 '11 at 19:33