Reputation: 21072
There are many examples over the net how to get pointer to byte[]
or int[,]
, i.e. when you know exactly the element type and rank of the array. But how to get the pointer for generic Array
?
The main problem here is I don't know rank in the advance. I don't know element type too but I know there can be only primitive numeric type (in my case), so I could type few extra if
s to cope with it.
Background: I would like to make this solution https://stackoverflow.com/a/52750659/6734314 more general -- in its current form it works only with double[,]
so classic rank+type is given:
double[,] doubles = {
{ 1, 2, 3, 4 },
...
};
fixed (double* p = doubles)
{
...
First attempt
From Olivier answer, all mistakes are mine.
Array data = new float[,] { { 4, 2 }, { 77, 3 } };
var reference = __makeref(data);
IntPtr pointer = **(IntPtr**)(&reference);
float* ptr = (float*)pointer.ToPointer();
{
for (int i = 0; i < data.LongLength; ++i)
Console.WriteLine(ptr[i]);
}
Upvotes: 1
Views: 1261
Reputation: 21072
I think I found it, please comment if you found something too fragile/suspicious:
Array data = new float[,] { { 4, 2 }, { 77, 3 } };
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
try
{
IntPtr address = handle.AddrOfPinnedObject();
float* ptr = (float*)address.ToPointer();
for (int i = 0; i < data.LongLength; ++i)
Console.WriteLine(ptr[i]);
}
finally
{
handle.Free();
}
Upvotes: 1
Reputation: 1062895
If the data is always the same shape (for example, 2D rectangular array), but potentially different types, then you can perhaps use the T : unmanaged
constraint and the fixed
keyword:
static void Main()
{
// sample taken from comtrade91.pdf section 6.6
var data = new float[,] { { 4, 2 }, { 77, 3 } };
ShowAddressAndData(data);
}
static unsafe void ShowAddressAndData<T>(T[,] data) where T : unmanaged
{
fixed(T* ptr = data)
{
Console.WriteLine((IntPtr)ptr);
for (int i = 0; i < data.Length; i++)
{
Console.WriteLine(ptr[i]);
}
}
}
// this extra method just to show that we can overload on dimension
static unsafe void ShowAddressAndData<T>(T[] data) where T : unmanaged
{
fixed (T* ptr = data)
{
Console.WriteLine((IntPtr)ptr);
//..
}
}
Upvotes: 2
Reputation:
Combining:
Memory address of an object in C#
And
How can I display a pointer address in C#?
Writing:
Array array = Array.CreateInstance(typeof(int), 10);
unsafe
{
var reference = __makeref(array);
var pointer = **(IntPtr**)( &reference );
Console.WriteLine("0x{0:x}", (ulong)&reference);
Console.WriteLine("0x{0:x}", (long)&reference);
Console.WriteLine("0x{0:x}", (ulong)pointer);
Console.WriteLine("0x{0:x}", (long)pointer);
}
Outputs:
0x8cb87af070
0x8cb87af070
0x1a9c1c46290
0x1a9c1c46290
Upvotes: 2