7
votes

IntPTR Arithmetics

J'ai essayé d'allouer une gamme de structures de cette manière:

T v;
v = (T)Marshal.PtrToStructure(data+1, typeof(T));


3 commentaires

La ptrtostructure copie des données. Si vous vous trouvez devant faire ce genre de choses, écrivez une bibliothèque non gérée et p / l'invoquer.


Peut-être que vous voulez expliquer pourquoi vous voulez travailler avec une gamme de valeurs dans la mémoire non gérée pour commencer. Vous pouvez créer un tableau géré et le maréchaler au code non géré. Aussi, vous dites "Safe", mais cela signifie-t-il que ce code marqué dangereux est hors de question ou voulez-vous simplement dire que vous ne voulez pas faire des erreurs?


Je mettant en œuvre l'abstraction d'objet tampon pour OpenGL. Les données attribuées pourraient contenir des sommets, des normales ... Je même affecter la mémoire en utilisant Allochglobal et gérer la mise en page des données, mais sans abandonner le séchanthique offert par ma mise en œuvre. GLVERTEXPOREPOPERDER: Il faut une adresse tampon et des informations sur la mise en page de la mémoire. Pourrais-je convertir T [] en intPTR sans copier des données (à l'aide de la mémoire de matrice directement à travers l'INTTE)?


5 Réponses :


2
votes

Vous pouvez utiliser l'adresse de mémoire intégrale de la structure du pointeur à l'aide de intptr.toint32 () mais méfiez-vous de la plate-forme "bitness" (32/64).

Pour les arithmétiques de pointeur typiques, utilisez des pointeurs d'utilisation (rechercher fixe et dangereux dans la documentation): xxx

édition:

i 'M Ponder que intPTR vous permet de gérer les pointeurs à des données sans explicitement manipuler adresses de pointeur. Cela vous permet d'interoper avec COM et code natif sans avoir à déclarer des contextes dangereux. La seule condition requise que l'exécution impose est la permission de code non gérée. Pour ces fins, il semble que la plupart des méthodes marshalling n'accepte que des données entièrement intPTR et non pure integer ou long Types, car il fournit une mince couche qui protège contre la manipulation du contenu de la structure. Vous pouvez manipuler les internes d'un intPTR directement, mais qui nécessitent soit des pointeurs dangereux (contextes non sécurisés) ou une réflexion. Enfin, IntPTR est automatiquement adopté à la taille du pointeur de la plate-forme.


0 commentaires

3
votes

En effet, le type intPTR ne possède pas ses propres opérateurs arithmétiques. Le pointeur correct (danger) arithmétique est prise en charge en C #, mais intPTR et le maréchal de la catégorie est "plus sûr" d'utilisation des pointeurs.

Je pense que vous voulez quelque chose comme ce qui suit: xxx

Aussi, note que intPtr n'a aucune conversion implicite entre int et intPTR , donc pas de chance là-bas.

Généralement, si vous allez faire quelque chose à distance complexe avec des pointeurs, il est probablement préférable d'opter pour un code dangereux.


3 commentaires

intPTR est un type primitif .NET. Vérifiez typeof (system.intptr) .isprimitive .


Oui, c'est ce que je cherchais. Mais peut-être qu'il est préférable d'allouer un tableau de struct et de le transmettre comme int. Mais je suis toujours plus fatiguant comment garantit que les champs de structure sont alignés correctement ...


Luca: [system.runtime.interopservices.tructlayout] spécifie les paramètres d'alignement et d'emballage pour une structure.



8
votes

"Pourquoi intPTR manque d'arithmétiques?"

intPTR stocke juste une adresse mémoire. Il n'a pas d'informations sur le contenu de cet emplacement de mémoire. De cette manière, il est similaire à vide * . Pour activer l'arithmétique du pointeur, vous devez connaître la taille de l'objet pointé vers.


fondamentalement, intPTR est principalement conçu pour être utilisé dans des contextes gérés en tant que poignée opaque (c'est-à-dire que vous n'avez pas de désarférence directement dans le code géré et que vous gardez simplement pour passer au code non géré. ) dangereux contexte fournit des pointeurs que vous pouvez manipuler directement.


0 commentaires

11
votes

Vous avez quatre options que je peux penser, deux en utilisant uniquement le code «Safe» et deux utilisateurs de code dangereux. Les options dangereuses sont susceptibles d'être nettement plus rapides.

Safe: h3>
  • Allouez votre matrice dans la mémoire gérée et déclarez votre fonction P / Invoke pour prendre la matrice. c'est-à-dire au lieu de: p>

    NativeType[] array = new NativeType[count];
    array[0].Member1 = foo;
    array[1].Member2 = bar;
    /* and so on */
    
    unsafe{
        fixed(NativeType* ptr = array)
            Foo(count, (IntPtr)ptr);
            // or just Foo(count, ptr), if Foo is declare as such:
            //     static unsafe bool Foo(int count, NativeType* arrayPtr);
    }
    


0 commentaires

0
votes

Vous pouvez utiliser classe d'échantillonnage pour une enveloppe autour des tableaux épingles afin que Je peux les utiliser avec IntPtr et le maréchalage Code: P>

    public static long Distance(this IntPtr a, IntPtr b)
    {
         return Math.Abs(((byte*)b) - ((byte*)a));
    }


0 commentaires