IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Petit problème de marshalling


Sujet :

C#

  1. #1
    Membre du Club
    Inscrit en
    Mars 2009
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 41
    Points : 57
    Points
    57
    Par défaut Petit problème de marshalling
    Bonjour,

    Donc problème de marshalling du jour , j'ai déclaré plusieurs classes qui sont équivalente à des classes déjà existante dans une application, ces classes permette de remplir un fichier binaire. Le but est de relire ces fichiers binaires depuis une nouvelle application c#. Donc j'ai recréé les classes en questions.
    Donc pour lire mon fichier j'utilise un objet BinaryReader dans lequel je récupère un tableau de Byte de taille = à la taille de ma structure.

    Petit exemple:

    Voila une de mes structure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
     
    [StructLayout(LayoutKind.Sequential)]
      class cScreenInfo
      {
        private int _idVersion;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
        private Byte[] _name;
        private short _id;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        private Byte[] _f1;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        private Byte[] _f2;
        private short _h;
        private short _w;
        private short _offX;
        private short _offY;
        private short _charWidth;
        private short _charHeight;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)]
        private short[] _arrayLineY;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
        private Byte[] _helpScreen;
     
        public static bool LireStructure(BinaryReader pFluxBinaire, out cScreenInfo pStructARemplir)
        {
          bool bRetour = true;
          Byte[] TableauByte;
          pStructARemplir = null;
          try
          {
            pStructARemplir = new cScreenInfo();
            cTestTmp test = new cTestTmp();
            int Size = Marshal.SizeOf(pStructARemplir);
            int Size2 = Marshal.SizeOf(test);
            IntPtr PtrDestination = Marshal.AllocHGlobal(Size);
            TableauByte = pFluxBinaire.ReadBytes(Size);
            Marshal.Copy(TableauByte, 0, PtrDestination, Size);
            pStructARemplir = (cScreenInfo)Marshal.PtrToStructure(PtrDestination, typeof(cScreenInfo));
          }
          catch (Exception e)
          {
            Loggers.Default.Error(e, "cScreenInfo.LireStructure(BinaryReader, cScreenInfo)");
            bRetour = false;
          }
          return bRetour;
        }
      }
    Y a un truc que je n'arrive pas à expliquer c'est le Sizeof de la classe Marshal me renvoie une taille supérieur de 2 octets à ce que je calcule. Donc derrière ça me décale mon pointeur dans mon flux binaire de 2 octets. Dans ce cas la pour moi la taille est de 200 octets et la il me retourne 202. Je voulais savoir si vous avez une idée de ou pouvez venir ces 2 octets supplémentaire. Apres comme le sizeof ne prend pas le type mais un objet...

  2. #2
    Inactif  
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Janvier 2007
    Messages
    6 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Points : 13 314
    Points
    13 314
    Par défaut
    Bonjour

    Sans doute un problème d'alignement.

    Utilise l'attribut StructLayout sur la classe pour forcer l'alignement des champs. (en général on utilise plutot une structure plutot que une classe, mais je ne sais pas si c'est susceptible de poser un problème).

    Je ne réponds pas aux questions techniques par MP ! Le forum est là pour ça...


    Une réponse vous a aidé ? utiliser le bouton

    "L’ennui dans ce monde, c’est que les idiots sont sûrs d’eux et les gens sensés pleins de doutes". B. Russel

  3. #3
    Membre du Club
    Inscrit en
    Mars 2009
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 41
    Points : 57
    Points
    57
    Par défaut
    J'ai fait le test avec une structure et même problème 2 octets de plus avec le Sizeof je vais regarder ce que je peux rajouter dans StructLayout qui serai susceptible de résoudre mon problème.
    Pour le moment j'ai trouvé un palliatif en reculant mon pointeur dans mon flux de 2 octets une fois ma classe initialisé. Mais bon j'aimerai bien comprendre.

    En gros ce que tu me conseil c'est de passer en explicite mon LayoutKind et rajouter des [FieldOffset(x)] devant mes champs pour cadrer le truc ?

  4. #4
    Inactif  
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Janvier 2007
    Messages
    6 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Points : 13 314
    Points
    13 314
    Par défaut
    Je viens de faire l'essai avec [StructLayout(LayoutKind.Sequential, Pack = 1)]et on passe bien de 104 à 102.

    Cela confirme un problème d'alignement.

    Par contre, je ne vois pas comment tu as calculé 200.

    Je ne réponds pas aux questions techniques par MP ! Le forum est là pour ça...


    Une réponse vous a aidé ? utiliser le bouton

    "L’ennui dans ce monde, c’est que les idiots sont sûrs d’eux et les gens sensés pleins de doutes". B. Russel

  5. #5
    Membre du Club
    Inscrit en
    Mars 2009
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 41
    Points : 57
    Points
    57
    Par défaut
    Ouai, je t'ai fillé une structure différente de c'elle ou j'ai calculé le nombre d'octet . Je creuse ton idée merci.

    Donc ça marche bien avec Pack = 1 et ce qui est louche mais bon le sens entre le c/c++ a peut être changé mais dans le .h du code C les structures sont déclaré en pragma Pack(2) mais si je met 2 du coté c# j'ai mes surplus d'octet.

    Next question :

    J'ai une imbrication de 3 classes est au final le Sizeof est au fraise et pour le moment je n'ai pas encore trouvé la solution.

    Voila la déclaration des 3 classes :

    cPoints:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
      class cPoint
      {
        public short X;
        public short Y;
        public short Order;
      }
    cArraypoint
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    [StructLayout(LayoutKind.Sequential, Pack=1)]
      class cArraypoint
      {
        public short Isarray;
        public short Size;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20, ArraySubType = UnmanagedType.Struct)]
        public cPoint[] Points;
      }
    et cSelectbox:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
      struct cSelectbox
      {
        #region Attributs privés
        public short _id;
        public short _ctvopt;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)]
        public Byte[] _infoBulle;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
        public Byte[] _name;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 80)]
        public Byte[] _message;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 11)]
        public Byte[] _ecranDAide;
        public Byte _lettreDAppel;
        public short _w;
        public short _h;
        [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
        public Byte[] _codeTouche;
        public Byte _champBits;
        [MarshalAs(UnmanagedType.Struct)]
        public cArraypoint _XY;
        #endregion
      }
    Et donc dans ce cas la le Sizeof me retourne 280 et coté c/c++ 322

  6. #6
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 441
    Points
    4 441
    Par défaut
    bonjour nazgul66.
    Les problemes d'alignements au frontiere sont recurrents avec les types personnalises (class ou structures) et il est vain de vouloir les eliminer.
    voici ce que dit la doc MSDN sur l'operateur sizeof en c++:
    When you apply the sizeof operator to a structure or union type name, or to an identifier of structure or union type, the result is the number of bytes in the structure or union, including internal and trailing padding. This size may include internal and trailing padding used to align the members of the structure or union on memory boundaries. Thus, the result may not correspond to the size calculated by adding up the storage requirements of the individual members
    Pour ce faire une vieille ficelle est d'etudier sa structure et de rajouter un membre "fantoche" pour avoir un alignement de frontiere type "byte" ou "word" suivant le besoin...
    Et par là voici ce que dit la doc MSDN sur l'operateur sizeof en c#:
    Pour tous les autres types, y compris structs, l'opérateur sizeof ne peut être utilisé que dans des blocs de code unsafe. Bien que vous puissiez utiliser la méthode SizeOf, la valeur retournée par cette méthode n'est pas toujours la même que la valeur retournée par sizeof. Marshal.SizeOf retourne la taille après que le type a été marshalé, alors que sizeof retourne la taille lorsqu'elle a été allouée par le Common Language Runtime, y compris un éventuel remplissage.
    il y a donc toujours des padding d'octets rajoutees à nos structs ou class pour avoir l'alignement memoire a cause du system d'adressage......et malgre l'utilisation des directives d'alignement
    bon code........................

  7. #7
    Inactif  
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Janvier 2007
    Messages
    6 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Points : 13 314
    Points
    13 314
    Par défaut
    Il y a visiblement un problème de traduction auto sur le bout de doc que tu passes, car justement l'opérateur sizeof ne peut pas être utilisé sur les types unsafe, ce qui implique l'utilisation de la méthode SizeOf sur l'instance elle même.

    Tu as le lien sur la page MSDN que tu cites ?

    Sinon :

    il y a donc toujours des padding d'octets rajoutees à nos structs ou class pour avoir l'alignement memoire a cause du system d'adressage......et malgre l'utilisation des directives d'alignement
    Quand on utilise les directives d'alignement à l'arménienne (abonescian ) je n'ai jamais constaté de problème, justement.

    Je ne réponds pas aux questions techniques par MP ! Le forum est là pour ça...


    Une réponse vous a aidé ? utiliser le bouton

    "L’ennui dans ce monde, c’est que les idiots sont sûrs d’eux et les gens sensés pleins de doutes". B. Russel

  8. #8
    Expert confirmé
    Inscrit en
    Avril 2008
    Messages
    2 564
    Détails du profil
    Informations personnelles :
    Âge : 64

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 564
    Points : 4 441
    Points
    4 441
    Par défaut
    bonjour BlueSeep
    ici le le lien pour sizeof pour le c++:
    http://www.google.fr/url?sa=t&rct=j&...WF5bSTedCXKLkA
    avec un exemple pour un tableau de string....
    La page MSDN est en anglais pas en armenien helas(chez moi j'ai la version french).....
    Et le lien pour le c# :
    http://www.google.fr/url?sa=t&rct=j&...WDbmJIqXr3T-ZQ
    et cette fois c'est en armenien ...pardon en francais.....

    Et voici un bout de code pris de la rubrique Marshal.Sizeof -qui founit taille du type non manage et taille de l'instance manage :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    // Demonstrate the use of the SizeOf method of the Marshal class.
    Console.WriteLine("Number of bytes needed by a Point object: {0}", 
        Marshal.SizeOf(typeof(Point)));
    Point p = new Point();
    Console.WriteLine("Number of bytes needed by a Point object: {0}",
        Marshal.SizeOf(p));

    bonne soiree..........

  9. #9
    Membre du Club
    Inscrit en
    Mars 2009
    Messages
    41
    Détails du profil
    Informations forums :
    Inscription : Mars 2009
    Messages : 41
    Points : 57
    Points
    57
    Par défaut
    Bonjour MABROUKI et Bluedeep, donc au final en repassant mes class cPoint et cArrayPoint en struct et le tout sur Pack 2 comme c'est fait dans le .h d'origine des structs je retombe sur la bonne taille. Je passe le sujet en résolu merci à vous deux.

  10. #10
    Inactif  
    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Janvier 2007
    Messages
    6 604
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet NTIC

    Informations forums :
    Inscription : Janvier 2007
    Messages : 6 604
    Points : 13 314
    Points
    13 314
    Par défaut
    Bonjour

    Citation Envoyé par MABROUKI Voir le message
    ici le le lien pour sizeof pour le c++:.
    Merci pour ces informations. Décidément, sur ces histoires de Marshaling et d'interop on en apprend tous les jours.....

    Je ne réponds pas aux questions techniques par MP ! Le forum est là pour ça...


    Une réponse vous a aidé ? utiliser le bouton

    "L’ennui dans ce monde, c’est que les idiots sont sûrs d’eux et les gens sensés pleins de doutes". B. Russel

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. un petit problème d'algo
    Par supertramp dans le forum Algorithmes et structures de données
    Réponses: 22
    Dernier message: 12/10/2004, 20h13
  2. Petit problème de décimales !
    Par ridan dans le forum Langage SQL
    Réponses: 5
    Dernier message: 11/09/2004, 21h24
  3. Réponses: 17
    Dernier message: 13/07/2004, 20h37
  4. petit problème premier plan, arrière plan
    Par gros bob dans le forum OpenGL
    Réponses: 4
    Dernier message: 19/04/2004, 12h00
  5. [jointure] Petit problème sur le type de jointure...
    Par SteelBox dans le forum Langage SQL
    Réponses: 13
    Dernier message: 13/02/2004, 18h55

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo