3

I have a multidimentional array of pointers to integer (of unknown rank) being passed into my function as such:

    public unsafe static void MyMethod(Array source, ...)
    {
         //...
    }

Multidimensional arrays of pointers are being constructed outside of the method and being passed in. Here's an example:

int*[,,,] testArray = new int*[10,10,5,5];

MyMethod(testArray);

How can I set a value at an runtime-computed index in the array? Array.SetValue(...) works perfectly fine for non-pointer arrays, but refuses to work for my int* array. Using reflector, I see SetValue reduces down to calling InternalSetValue which takes an object for the value but it's marked as extern and I can't see the implementation. I took a shot in the dark and tried passing in boxed pointer, but no luck.

Robert Venables
  • 5,943
  • 1
  • 23
  • 35

2 Answers2

4

This works:

unsafe static void MyMethod(int** array)
{
    array[10] = (int*)0xdeadbeef;
}

private static unsafe void Main()
{
    int*[, , ,] array = new int*[10, 10, 10, 10];

    fixed (int** ptr = array)
    {
        MyMethod(ptr);
    }

    int* x = array[0, 0, 1, 0]; // == 0xdeadbeef
}

Does that help?


Question to the experts: Is it wrong to assume that the array is allocated consecutively in memory?

dtb
  • 213,145
  • 36
  • 401
  • 431
  • @Maximilian: Thanks. Is this documented somewhere? Or is it an implementation detail if the CLR? – dtb Dec 07 '09 at 19:03
  • 3
    Yes, this is specified by Ecma-335 (CLI spec): "Array elements shall be laid out within the array object in row-major order (i.e., the elements associated with the rightmost array dimension __shall be laid out contiguously__ from lowest to highest index)." – Pavel Minaev Dec 07 '09 at 19:07
1

This doesn't work because it's not possible to box a pointer in .NET, so you can never call the Array.SetValue and pass an int*.

Can you declare MyMethod to accept int*[,,,] instead?

Edit: for further reading, an interesting recent post from Eric Lippert.

Tim Robinson
  • 53,480
  • 10
  • 121
  • 138
  • The requirement for the method is that it works with an array of any dimension. Also, see: http://msdn.microsoft.com/en-us/library/system.reflection.pointer.box.aspx – Robert Venables Dec 07 '09 at 18:47
  • OK, but Array.SetValue doesn't know how to unbox a pointer boxed using Pointer.Box: I get "System.NotSupportedException: Type is not supported." – Tim Robinson Dec 07 '09 at 18:51
  • I found that out (see above) - It's actually Array.InternalGetReference (also marked as extern) throwing that exception. – Robert Venables Dec 07 '09 at 19:08