none
C# [Tip] - Envoyer des structures entre mémoire managée et non-managée RRS feed

  • Discussion générale

  • Juste pour des buts didactiques, cet article présente la modalité de transfert des structures entre la mémoire managée et la mémoire non-managée.

     

    On va créer deux structures avec la même taille. La seule différence est que la première structure à deux membres, un UInt16 et un UInt32, et la deuxième structure à trois membres de type UInt16.

     

    A l’aide de la classe Marshall, on va essayer de mapper la première structure sur la deuxième et voir ce que se passe avec les valeurs des variables membres.

     

    [StructLayout(LayoutKind.Explicit)]
     public struct MyStruct
     {
     [FieldOffset(0)] public UInt16 a;
     [FieldOffset(2)] public UInt32 b;
     }
    
     [StructLayout(LayoutKind.Explicit)]
     public struct PirateStruct
     {
     [FieldOffset(0)] public UInt16 x;
     [FieldOffset(2)] public UInt16 y;
     [FieldOffset(4)] public UInt16 z;
     }
    
    

     

     

    Voici la représentation dans la mémoire de ces structures :

     

    Dans la structure MyStruct, on met la valeur 1 et 65536. Le deuxième membre de cette structure peut garder des valeurs comprises sur 4 octets. Les valeurs jusqu’à 65535 sont gardées sur les premiers 2 octets, et les valeurs supérieures commencent à utiliser les autres 2 octets aussi.

     

    Pour la valeur 65535 :

     

     

    Pour la valeur 65536 :

     

     

    Quand on va mapper cette structure sur la structure PirateStructure, ces séries de bits vont former des valeurs différentes, car la structure PirateStructure à des membres de types différents :

     

     

     

     

    Voici le code qui permet de faire une telle manipulation :  

               

     

     

     

     

     

    PirateStruct pirateStruct = new PirateStruct();
      pirateStruct.x = 0;
      pirateStruct.y = 0;
      pirateStruct.z = 0;
    
      MyStruct myStruct = new MyStruct();
      myStruct.a = 1;
      myStruct.b = 65536;
    
      IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(myStruct));
      Marshal.StructureToPtr(myStruct, ptr, false);  
      pirateStruct = (PirateStruct)Marshal.PtrToStructure(ptr, typeof(PirateStruct));
      Console.WriteLine("x={0}, y={1}, z={2}", pirateStruct.x, pirateStruct.y, pirateStruct.z);
    
    
    
    

     

    Pour plusieurs questions sur C#, visitez Foire aux Questions – C# FAQ et Tutoriels

     

     

     

     

    jeudi 8 juillet 2010 12:19