Comment obtenir un pointeur vers la mémoire de l'instance Array?
Il existe de nombreux exemples sur le net comment obtenir un pointeur vers byte[]ou int[,], c'est-à-dire quand vous connaissez exactement le type d'élément et le rang du tableau. Mais comment obtenir le pointeur du générique Array?
Le principal problème ici est que je ne connais pas le rang d'avance. Je ne connais pas non plus le type d'élément mais je sais qu'il ne peut y avoir que du type numérique primitif (dans mon cas), donc je pourrais taper quelques ifs supplémentaires pour y faire face.
Contexte: je voudrais faire de cette solution https://stackoverflow.com/a/52750659/6734314plus général - dans sa forme actuelle, il ne fonctionne qu'avec le double[,]type de rang + classique:
double[,] doubles = {
{ 1, 2, 3, 4 },
...
};
fixed (double* p = doubles)
{
...
Premier essai
De la réponse d'Olivier, toutes les erreurs sont les miennes.
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]);
}
Réponses
Combinaison:
Adresse mémoire d'un objet en C #
Et
Comment puis-je afficher une adresse de pointeur en C #?
L'écriture:
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);
}
Les sorties:
0x8cb87af070
0x8cb87af070
0x1a9c1c46290
0x1a9c1c46290
Code source de la classe Array
Si les données ont toujours la même forme (par exemple, un tableau rectangulaire 2D), mais potentiellement des types différents , vous pouvez peut-être utiliser la T : unmanagedcontrainte et le fixedmot - clé:
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);
//..
}
}
Je pense que je l'ai trouvé, veuillez commenter si vous avez trouvé quelque chose de trop fragile / suspect:
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();
}