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++/CLI Discussion :

Marshal.SizeOf avec layout explicite renvoie une taille fausse ?!


Sujet :

C++/CLI

  1. #1
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut Marshal.SizeOf avec layout explicite renvoie une taille fausse ?!
    Salut,

    J'ai un problème étrange avec Marshal.SizeOf...

    Je souhaite manipuler la structure native suivante (en-tête d'un fichier bitmap) :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    typedef struct tagBITMAPFILEHEADER { 
      WORD    bfType; 
      DWORD   bfSize; 
      WORD    bfReserved1; 
      WORD    bfReserved2; 
      DWORD   bfOffBits; 
    } BITMAPFILEHEADER, *PBITMAPFILEHEADER;

    J'ai donc écrit l'équivalent en C# :
    Code C# : 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
            [StructLayout(LayoutKind.Explicit)]        
            private struct BITMAPFILEHEADER
            {
                public static readonly short BM = 0x4d42; // BM
     
                [FieldOffset(0)]
                public short bfType;
                [FieldOffset(2)]
                public int bfSize;
                [FieldOffset(6)]
                public short bfReserved1;
                [FieldOffset(8)]
                public short bfReserved2;
                [FieldOffset(10)]
                public int bfOffBits;
            }
    Le layout explicite est nécessaire pour que le marshalling n'aligne pas les champs sur les bornes de 32bits (ça décalerait tous les champs à partir du 2e, ce qui corromprait l'en-tête).

    Quand je copie cette structure vers la mémoire non-managée avec Marshal.Copy, le layout explicite est bien pris en compte et les données binaires sont correctes.

    Par contre, Marshal.SizeOf me renvoie 16
    Pourtant, j'ai beau compter et recompter, ça fait 14... d'ailleurs si j'écris 16 octets d'en-tête, le fichier est incorrect et illisible. Si je ne tiens pas compte de ce que dit Marshal.Sizeof et que j'utilise une taille de 14, ça fonctionne nickel.

    En fait, on dirait qu'il ne tient pas compte du layout explicite dans le calcul de la taille J'ai aussi essayé avec l'opérateur sizeof (dans un bloc unsafe), le résultat est le même.

    Bref, je ne trouve aucun moyen d'obtenir une taille correcte autrement qu'en la codant en dur. Quelqu'un aurait une idée de comment faire ? Ou une explication de ce comportement ?

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Hum... bon, apparemment il suffisait que j'énonce clairement le problème pour trouver la solution... j'y ai pensé en écrivant le post, j'ai essayé juste après, et c'était ça. Comme quoi j'aurais du tester avant de poster

    Il suffisait d'ajouter dans l'attribut StructLayout le paramètre Pack = 2 :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
            [StructLayout(LayoutKind.Explicit, Pack = 2)]
            private struct BITMAPFILEHEADER


    Pour info, l'objectif est d'effectuer le décodage d'un DIB (DeviceIndependentBitmap) récupéré du presse-papiers, pour contourner un bug de la classe Clipboard de WPF. Maintenant que ce problème est réglé, tout marche, je posterai le code d'ici peu...

    EDIT: avec Pack = 2, plus besoin du layout explicite, le séquentiel marche nickel... donc on peut faire sauter tous les FieldOffset

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

Discussions similaires

  1. Nagios check_total_procs renvoie une réponse fausse via NRPE
    Par pausg dans le forum Administration système
    Réponses: 0
    Dernier message: 27/09/2011, 11h30
  2. Calendar.getInstance() renvoie une date fausse
    Par Phonatacid dans le forum Collection et Stream
    Réponses: 2
    Dernier message: 26/05/2009, 12h40
  3. sauter une ligne avec Layout...
    Par youp_db dans le forum Agents de placement/Fenêtres
    Réponses: 3
    Dernier message: 16/12/2005, 19h54
  4. problème avec le recupération de la taille d'une image
    Par vbcasimir dans le forum Modules
    Réponses: 5
    Dernier message: 28/11/2005, 17h20
  5. Bloquer une taille de CView avec OnSize
    Par vanitom dans le forum MFC
    Réponses: 3
    Dernier message: 17/11/2005, 11h13

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