Convertir un tableau de structures en IntPtr
Je suis en train de convertir un tableau de la structure RECT (ci-dessous) dans un IntPtr, pour que je puisse envoyer le pointeur à l'aide de PostMessage à une autre application.
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
//lots of functions snipped here
}
//so we have something to send, in reality I have real data here
//also, the length of the array is not constant
RECT[] foo = new RECT[4];
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(foo[0]) * 4);
Marshal.StructureToPtr(foo, ptr, true); //-- FAILS
Cela donne une ArgumentException sur la dernière ligne ("La structure spécifiée doit être blittable ou avoir des informations de mise en page."). J'ai besoin d'obtenir en quelque sorte ce tableau de Rectangles vers une autre application à l'aide de PostMessage, donc j'ai vraiment besoin d'un pointeur à ces données.
Quelles sont mes options?
Mise à JOUR: Cela semble fonctionner:
IntPtr result = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Win32.RECT)) * foo.Length);
IntPtr c = new IntPtr(result.ToInt32());
for (i = 0; i < foo.Length; i++)
{
Marshal.StructureToPtr(foo[i], c, true);
c = new IntPtr(c.ToInt32() + Marshal.SizeOf(typeof(Win32.RECT)));
}
De NOUVEAU mis à JOUR pour corriger ce qui arbitre commenté.
source d'informationauteur Vegard Larsen | 2009-07-06
Vous devez vous connecter pour publier un commentaire.
StructureToPtr attend struct objet, et foo n'est pas la structure, il est tableau, c'est pourquoi exception se produit.
Je peux vous suggérer d'écrire des structures dans le cycle (malheureusement, StructureToPtr ne pas avoir de surcharge avec Index):
Une autre option est d'écrire structure de quatre entiers, à l'aide de Maréchal.WriteInt32:
Et le dernier, vous pouvez utiliser dangereux mot-clé, et de travailler avec des pointeurs directement.
Arbitre vous a donné une bonne réponse à comment maréchal des tableaux de structures. Pour blittable des structures comme celles-ci, je, personnellement, serait d'utiliser le code unsafe plutôt que manuellement marshaling chaque élément de mémoire non managée. Quelque chose comme ceci:
ou vous pouvez épingler le tableau à l'aide d'un GCHandle.
Malheureusement, vous dites que vous avez besoin d'envoyer cette information à un autre processus. Si le message que vous envoyez n'est pas un de ceux pour qui Windows fournit automatique marshaling alors vous avez un autre problème. Depuis le pointeur est relatif au processus local ne signifie rien dans le processus à distance et l'affichage d'un message avec ce pointeur va provoquer un comportement inattendu, y compris plantage du programme. Donc, ce que vous devez faire est d'écrire le RECT tableau à l'autre du processus de la mémoire ne sont pas les vôtres. Pour ce faire, vous devez utiliser OpenProcess pour obtenir un handle pour le processus, VitualAllocEx pour allouer de la mémoire dans les autres processus, puis WriteProcessMemory écrire la matrice dans les autres processus de la mémoire virtuelle.
Malheureusement, encore une fois, si vous allez à partir d'un processus 32 bits à un processus 32 bits ou d'un 64bit processus 64 bits processus, les choses sont assez simples, mais à partir d'un processus 32 bits à 64 bits processus, les choses peuvent devenir un peu poilue. VirtualAllocEx et WriteProcessMemory ne sont pas vraiment pris en charge à partir de 32 à 64 ans. Vous pouvez avoir du succès en essayant de forcer VirtualAllocEx pour allouer de la mémoire dans le fond le 64 bits 4 go de mémoire, d'espace, de sorte que le pointeur est valide pour les processus 32 bits appels d'API, puis d'écrire avec le pointeur. En outre, vous pouvez avoir struct la taille et à l'emballage des différences entre les deux types de processus. Avec RECT il n'y a pas de problème, mais certains autres structures avec l'emballage ou l'alignement des questions peut-être besoin d'être écrit manuellement champ par champ pour le 64 bits processus afin de correspondre à la 64bit structure de mise en page.
Vous pouvez essayer les suivantes:
Et n'oubliez pas de libérer tout ce qui est après vous avez terminé.
Je n'ai pu obtenir que cette solution fonctionne. J'ai donc fait quelques recherches et la solution donnée ici a fonctionné pour moi.
http://social.msdn.microsoft.com/Forums/en-US/clr/thread/dcfd6310-b03b-4552-b4c7-6c11c115eb45