6
votes

Existe-t-il une alternative pour l'attribut StructLayout "Pack" dans le cadre compact?

Je voudrais faire ce qui suit:

[StructLayout(LayoutKind.Explicit, Size=8)]
public struct SomeStruct
{
   [FieldOffset(0)]
   public byte SomeByte;
   [FieldOffset(1)]
   public int SomeInt;
   [FieldOffset(5)]
   public short SomeShort;
   [FieldOffset(7)]
   public byte SomeByte2;
}


6 commentaires

Vous avez commenté «la mise en page explicite ne résout pas le problème» - quel est le problème réel que vous souhaitez résoudre? Qu'est-ce qui ne fonctionne actuellement pas.


Essayer d'emballer la structure de sorte que la taille s'avère être de 8 octets. Sans l'attribut Pack de pack, la taille est mise au rebut plus grande que prévu (en raison de la taille d'emballage par défaut)


La solution peut impliquer des maréchalements de champs individuels de la structure pour déterminer la taille (aussi, notez que je pourrais également avoir des matrices à l'intérieur de ma structure); Qui introduit plus de problèmes, comme le montre mon autre poste ici: Stackoverflow.com/ Questions / 1268898 / ...


Si ma réponse n'est pas autorisée parce que vous en avez besoin comme une forme marshaled de certaines struct définies ailleurs, vous n'avez aucune option, mais de déclarer une structure d'octets / INTS / quoi que ce soit avec un alignement acceptable et que vous vous décongeliez le respect de l'endianesse, etc.)


J'ai fourni un travail autour, bien qu'un douloureux, il a répondu à vos besoins


Ce serait bien si nous pouvions avoir une sorte de maréchaler personnalisé universel qui a utilisé une réflexion. Mais en faisant cela, vous réécrivez fondamentalement et prolongeriez le cadre de maréchalage intégré. Sauf si vous avez mis dans une quantité incroyable de travail, ce serait horriblement fragile et probablement inutilisable.


7 Réponses :


1
votes

Vous devez poster un exemple plus pertinent. Mise en place de l'emballage sur cette structure n'aurait aucun effet de toute façon.

Mon pari est que vous devez utiliser Laoutkind.Explicit et ensuite donner les compensations pour chaque membre. C'est bien mieux que de jouer avec l'emballage de toute façon, car il est bien plus évident pour une personne qui examine le code que le développeur original signifiait explicitement pour que les choses soient inalignées.

quelque chose sur ces lignes: < Pré> xxx


0 commentaires

0
votes

layoutkind.explicit serait votre meilleur choix pour définir une mise en page spécifique de la mémoire. Toutefois, ne pas utiliser layoutkind.explicite pour les structures contenant des valeurs de pointeur tels que des pointeurs tristes, des poignées du système d'exploitation ou intPTR s; Cela ne veut que demander des problèmes mystérieux au moment de l'exécution sur des plates-formes aléatoires.

en particulier, layoutkind.explicit est un substitut médiocre des syndicats anonymes . Si votre structure cible contient une union anonyme, convertissez-la en union nommée; Vous pouvez représenter en toute sécurité une union nommée comme structure avec layoutkind.explicit tous les compensations sont 0 . .


3 commentaires

La mise en page explicite avec des pointeurs est en fait une pratique courante dans les FC où le marshallateur suce et ne peut pas le faire pour vous.


D'accord, le marshaller des FC est faible. J'utilise habituellement la deuxième technique, cependant: layoutkind.Ensuite dans la mesure du possible et convertissez des syndicats anonymes aux nommés.


@Jeffreyhantin Si vous pouvez modifier tout le code impliqué ou au moins de la ré-compiler, alors oui, l'utilisation de syndicats anonymes est une mauvaise décision. Mais souvent, il s'agit d'un correctif pour une incohérence. Par exemple, ECMA-334 permet auum de contenir n'importe quelle valeur du type sous-jacent. Mais la plupart des cours de BCL ignorent complètement cette "fonctionnalité", également des sérialiseurs forcent souvent l'énum.isdefined. Une façon d'aller est de se chevaucher enum avec un entier public. Et oui, je sais que c'est étrange de poster sur des sujets datés de "09 =)



4
votes

La méthode la plus simple de traiter ce type de problème est le long des mêmes lignes que vous pourriez pour un champ de bit, appuyez simplement vos données dans un membre privé (ou des membres si elle est grande) du type de données approprié, puis présent. Propriétés publiques qui décompressent les données pour vous. Les opérations de déballage sont extrêmement rapides et auront peu d'impact sur la performance. Pour votre type particulier, ce qui suit est probablement ce que vous voulez: xxx

pour certaines structures même, cette méthode n'est pas utilisable en raison de la maladie malheureuse une structure a été définie. Dans ces cas, vous devrez généralement utiliser une matrice d'octets comme une blob de données à partir de laquelle les éléments peuvent être déballés.

Edit: pour développer ce que je veux dire sur les structures qui ne peuvent pas être traitées à l'aide de cette méthode simple. Lorsque vous ne pouvez pas faire de simples emballage / déballage comme celui-ci, vous devez fermer manuellement la structure irrégulière. Cela peut être fait à l'aide de méthodes manuelles au point que vous appelez l'API BLVVOKED ou en utilisant un maréchaleur personnalisé. Vous trouverez ci-dessous un exemple de marhysaler personnalisé qui peut être facilement adapté au maréchalage manuel de la tache. xxx

dans le cas des tableaux de ces structures, vous ne pouvez pas utiliser la maréchalation personnalisée, à moins que la taille de la matrice ne soit corrigée, mais il est relativement facile de repousser manuellement les données de réseau dans son ensemble. en utilisant les mêmes techniques.


0 commentaires

0
votes

Layoutkind.Explicite et FieldOffsetattribute vous permettront de faire tout ce que vous pourriez faire avec la propriété Pack. Ces attributs de mise en page explicite vous permettent de spécifier la position exact des octets de chaque champ dans la structure (par rapport au début de la plage de mémoire de la structure). La propriété Pack est utilisée par l'exécution pour déterminer la position exacte de chaque champ lors de l'utilisation d'une disposition séquentielle. La propriété Pack n'a pas d'autre effet. L'utilisation de la mise en page explicite vous permet d'imiter exactement le même comportement, même si un peu plus verboisement. Si vous ne pensez pas que cela résout votre problème, vous pourriez peut-être poster un peu plus d'informations sur ce que vous essayez de faire ou pourquoi vous pensez avoir besoin d'utiliser la propriété Pack.

Edit: Je viens de remarquer le commentaire supplémentaire sur la tentative d'obtenir la taille de la structure totale à 8 octets. Avez-vous essayé d'utiliser la propriété StructLayOntAttribute.Size? Contrairement à Pack, il est disponible dans le cadre compact.


1 commentaires

Voir ma mise à jour2. La propriété de taille ne aide pas (je pense que cela va en réalité une cassette dactylographique à la taille de la taille inférieure à la taille de la structure réelle en utilisant explicite)



6
votes

Ce n'est probablement pas le type de réponse que vous recherchez, mais je le posterai de toute façon pour l'enfer:

public struct SomeStruct
{
    public byte SomeByte;
    public int SomeInt;
    public short SomeShort;
    public byte SomeByte2;


    public byte[] APIStruct
    {
        get
        {
            byte[] output = new byte[8];
            output[0] = this.SomeByte;
            Array.Copy(BitConverter.GetBytes(this.SomeInt), 0,
                output, 1, 4);
            Array.Copy(BitConverter.GetBytes(this.SomeShort), 0,
                output, 5, 2);
            output[7] = this.SomeByte2;
            return output;
        }
        set
        {
            byte[] input = value;
            this.SomeByte = input[0];
            this.SomeInt = BitConverter.ToInt32(input, 1);
            this.SomeShort = BitConverter.ToInt16(input, 5);
            this.SomeByte2 = input[7];
        }
    }
}


6 commentaires

Oui, c'est une approche qui pourrait fonctionner, j'espérais éviter manuellement de vous indexer, mais peut-être que c'est la meilleure solution.


Je pense que cela pourrait être modifié pour itérer à travers les propriétés et utiliser la taille de ou tout ce qui est de l'emballer dans un octet [], de sorte que vous n'auriez donc pas à indexer manuellement tout. C'était juste un échantillon rapide. Un autre avantage est que cela fonctionnerait dans les FC ou le cadre complet sans modification (mais je pense que je suis peut-être la seule personne qui écrit des applications qui se déroulent sans recompilation).


J'essaie: P Je voulais certainement quelque chose qui pourrait courir sur les deux cadres.


Juste au cas où je me manque quelque chose, je suis curieux de savoir comment c'est différent de la réponse que j'ai écrite il y a 2 jours?


@Stephen: C'est plus simple et plus lisible, imho. Autre que cela, c'est le même principe de base.


Assez juste. Je pensais que je pourrais avoir mal comprendre quelque chose.



2
votes

Êtes-vous absolument besoin em> cette mise en page spécifique ou est-ce acceptable de simplement faire la taille 8?

Je le demande comme suit comme suit P>

[StructLayout(LayoutKind.Explicit, Size=8)]
public struct SomeStruct
{ 
   [FieldOffset(0)] private byte b0;
   [FieldOffset(1)] private byte b1;
   [FieldOffset(2)] private byte b2;
   [FieldOffset(3)] private byte b3;
   [FieldOffset(4)] private byte b4;
   [FieldOffset(5)] private byte b5;
   [FieldOffset(6)] private byte b6;
   [FieldOffset(7)] private byte b7;

   // not thread safe - alter accordingly if that is a requirement
   private readonly static byte[] scratch = new byte[4];       

   public byte SomeByte 
   { 
       get { return b0; }
       set { b0 = value; }
   }

   public int SomeInt
   {
       get 
       { 
           // get the right endianess for your system this is just an example!
           scratch[0] = b1;
           scratch[1] = b2;
           scratch[2] = b3;
           scratch[3] = b4;
           return BitConverter.ToInt32(scratch, 0);
       }
   }

   public short SomeShort
   {
        get 
        { 
            // get the right endianess for your system this is just an example!
            scratch[0] = b5;
            scratch[1] = b6;
            return BitConverter.ToInt16(scratch, 0);
        }
    }

    public byte SomeByte2 
    { 
        get { return b7; }
        set { b7 = value; }
    }
}


1 commentaires

Merci pour la poche shuggy et en donnant cela. Je me rends compte que c'est un problème d'alignement, mais j'ai besoin de garder la structure comme c'est (format de message spécifique).



1
votes

Je pense que l'on devrait prendre la réponse de Stephen Martin, le faire accepter un T et utiliser la réflexion pour mettre en œuvre de manière générique les méthodes marshalagédonative et marshalnativetomatique. Ensuite, vous aurez un maréchaler de structure emballée personnalisé qui fonctionnera pour tout type de structure.

Voici le code: xxx


0 commentaires