11
votes

Convertir une palette de structures en intPR

J'essaie de convertir une matrice de la structure rectoire (donnée ci-dessous) dans un INTPTR, je peux donc envoyer le pointeur à l'aide de postmessage à une autre application.

 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)));
 }


4 commentaires

Quel message postez-vous que cela effectue automatiquement le maréchalage croisé d'un tableau de 4 rects?


Je tente de dire à une DLL (qui est hébergé dans un autre processus car il est 64 bits) d'ignorer certaines régions de l'écran. Ce n'est pas nécessairement 4 rect.


Selon votre mise à jour, vous ne répartissez pas assez d'espace (IntPTR.Size au lieu de maréchal.Sizeof (typeof (rect))). Et votre pointeur arithmétique peut échouer sur des machines x64, voir ma réponse.


En réalité, l'arithmétique du pointeur échouera, car l'exécutable de ce code est en strictement 32 bits et ne peut jamais devenir 64 bits. :) Mais vous êtes correct sur les allocations.


4 Réponses :


0
votes

Vous pouvez essayer ce qui suit:

 RECT[] rects = new RECT[ 4 ];
 IntPtr[] pointers = new IntPtr[4];
 IntPtr result =  Marshal.AllocHGlobal(IntPtr.Size * rects.Length);
 for (int i = 0; i < rects.Length; i++)
 {
     pointers[i] = Marshal.AllocHGlobal (IntPtr.Size);
     Marshal.StructureToPtr(rects[i], pointers[i], true);
     Marshal.WriteIntPtr(result, i * IntPtr.Size, pointers[i]);
 }
 // the array that you need is stored in result


1 commentaires

Sauf que ceci est un éventail de pointeurs vers des rectors non un tableau de rects. Et vous allociez des blocs de mémoire de pointeur de la mémoire pour chacun des pointeurs [i], mais ensuite marshalant 16 octets (taille de (rect)) à cet endroit. Ce type de débordement est une recette pour la catastrophe.



13
votes

Structuetoptr s'attend à ce que la structure objet, et foo n'est pas structurée qu'elle est une matrice, c'est pourquoi une exception se produit.

Je peux vous suggérer d'écrire des structures en cycle (tristement, Structuetoptr n'a pas de surcharge avec index): xxx

Une autre option consiste à écrire une structure comme quatre entiers, à l'aide de marshal.writeint32: xxx

et le dernier, vous pouvez utiliser < forte> dangereux mot-clé et travailler avec des pointeurs directement.


0 commentaires

1
votes

Arbitre vous a donné une bonne réponse pour comment faire des maréhals de structs. Pour les structures blitables comme celles-ci, je voudrais utiliser un code dangereux plutôt que de marchaser manuellement chaque élément à la mémoire non gérée. Quelque chose comme ceci: xxx

ou vous pouvez épingler le tableau à l'aide d'un gchandle.

Malheureusement, vous dites que vous devez envoyer ces informations à un autre processus. Si le message que vous publiez n'est pas l'un quelconque de ceux pour lesquels Windows fournit un maréchalage automatique, vous avez un autre problème. Étant donné que le pointeur est relatif au processus local, cela ne signifie rien dans le processus distant et l'affichage d'un message avec ce pointeur entraînera un comportement inattendu, y compris une crash de programme probable. Donc, ce que vous devez faire est d'écrire le tableau record à l'autre processus de processus, pas le vôtre. Pour ce faire, vous devez utiliser OpenProcess pour obtenir une poignée au processus, VitualallOcex pour allouer la mémoire dans l'autre processus, puis écroîtreProcessmemory pour écrire le tableau dans l'autre processus de la mémoire virtuelle.

Malheureusement, si vous passez d'un processus de 32 bits à un processus de 32 bits ou d'un processus de 64 bits à un processus de 64 bits, les choses sont assez simples, mais à partir d'un processus de 32 bits à un processus de 64 bits, les choses peuvent être un peu velues. . VirtualallOcEx and SRICEProcessMemory n'est pas vraiment pris en charge de 32 à 64. Vous pouvez avoir du succès en essayant de forcer VirtualallOceX à allouer sa mémoire dans les 4 Go inférieurs de l'espace mémoire 64 bits afin que le pointeur résultant soit valide pour les appels d'API de process 32 bits, puis écrivez avec ce pointeur. De plus, vous pouvez avoir une taille de structure et des différences d'emballage entre les deux types de processus. Avec un nouveau problème, il n'y a pas de problème, mais certaines autres structures avec des problèmes d'emballage ou d'alignement devraient devoir être écrits manuellement sur le terrain au processus 64 bits afin de correspondre à la disposition de la structure 64 bits.


0 commentaires

0
votes

J'étais incapable de faire fonctionner cette solution. Donc, j'ai fait des 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


0 commentaires