Bagaimana cara mendapatkan pointer ke memori instance Array?
Ada banyak contoh di internet bagaimana mendapatkan pointer ke byte[]or int[,], yaitu ketika Anda tahu persis jenis elemen dan peringkat array. Tetapi bagaimana cara mendapatkan pointer untuk generik Array?
Masalah utama di sini adalah saya tidak tahu peringkat sebelumnya. Saya tidak tahu tipe elemen juga tapi saya tahu hanya ada tipe numerik primitif (dalam kasus saya), jadi saya bisa mengetik beberapa tambahan ifuntuk mengatasinya.
Latar Belakang: Saya ingin membuat solusi ini https://stackoverflow.com/a/52750659/6734314lebih umum - dalam bentuknya saat ini ia hanya berfungsi dengan double[,]begitu tipe rank + klasik diberikan:
double[,] doubles = {
{ 1, 2, 3, 4 },
...
};
fixed (double* p = doubles)
{
...
Percobaan pertama
Dari jawaban Olivier, semua kesalahan adalah milik saya.
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]);
}
Jawaban
Menggabungkan:
Alamat memori suatu objek di C #
Dan
Bagaimana cara menampilkan alamat penunjuk di C #?
Penulisan:
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);
}
Keluaran:
0x8cb87af070
0x8cb87af070
0x1a9c1c46290
0x1a9c1c46290
Kode sumber kelas Array
Jika datanya selalu dalam bentuk yang sama (misalnya, larik persegi panjang 2D), tetapi kemungkinan jenisnya berbeda , Anda mungkin dapat menggunakan T : unmanagedbatasan dan fixedkata kunci:
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);
//..
}
}
Saya rasa saya menemukannya, beri komentar jika Anda menemukan sesuatu yang terlalu rapuh / mencurigakan:
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();
}