Marshaling. Struct na byte[] i problem.

0

Witam. Chcę zserializować struct na tablicę bajtów, ale coś się sypie.. mianowicie tablica wyjściowa ma cały czas stały rozmiar (60) i całkowicie nie zgadza się z wartościami zmiennych, i sądzę, że ma to związek z byte[] jako zmienne w strukturze:

[Serializable]
    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
    struct GGLOGIN_80
    {
        public int Uin;
        public byte[] Lang;
        public byte HashType;
        public byte[] Hash;
        public int Status;
        public int Flags;
        public int Features;
        public int LocalIP;
        public short LocalPort;
        public int ExternalIP;
        public short ExternalPort;
        public byte ImageSize;
        public byte Unknown1;
        public int VerLength;
        public byte[] Ver;
        public int DescSize;
        public byte[] Desc;
    }

Przykładowo do Lang przypisuje new byte[2] {'p', 'l'}; i wychodzą za każdym razem INNE wartości na pozycjach w tablicy. Jedynie pierwsza zmienna (Uin) gdy przypiszę 100, w tablicy jest {100, 0, 0, 0}.

Serializacja:

byte[] obj = new byte[Marshal.SizeOf(packet)];
            IntPtr p = Marshal.AllocHGlobal(obj.Length);
            Marshal.StructureToPtr(packet, p, false);
            Marshal.Copy(p, obj, 0, obj.Length);
            Marshal.FreeHGlobal(p);

Jak zserializować prawidłowo tę strukturę? Myślę, że przyczyną są te tablice byte[], ale jak to naprawić? Dodam, że długości tablic byte[] są zmienne i mogą mieć różne wartości.

0

Dodam, że długości tablic byte[] są zmienne i mogą mieć różne wartości.

Domyślnie jest ona zamieniana na wskaźnik, ew. można za pomocą atrybutu podać jej stały rozmiar. W przypadku rozmiaru znanego dopiero w runtime musisz sam sobie napisać marshalling (zwykły binarystream i zapisanie do niego po kolei pól tutaj wystarczy).

0

Totalnie wypadło mi z głowy, że to przecież referencja, a nie wartość >.< Dzięki więc, napiszę to z wykorzystaniem BinaryWriter'a tak jak mówisz. Szkoda jednak, że nie da się tego standardowo marshalingiem. W ogóle próbowałem BinaryFormatter'em, ale wychodziło mi coś innego niż serializacja pól po kolei jak w marshalingu.

0

No przecież się da. Tylko musi być rozmiar stały.

[MarshalAs(UnmanagedType.ByValArray, SizeConst=2)]
public byte[] Lang;

Możesz też przekazać jako wskaźnik, wtedy rozmiar może być zmienny:

[MarshalAs(UnmanagedType.LPArray)]
public byte[] Lang;

Przekazywanie tablicy o zmiennym rozmiarze przez wartość wewnątrz struktury raczej nie ma sensu, przecież powodowałoby przesuwanie wszystkich kolejnych pól struktury.

0

No przecież się da. Tylko musi być rozmiar stały.

Nie da się, bo rozmiar nie jest stały.

Przekazywanie tablicy o zmiennym rozmiarze przez wartość wewnątrz struktury raczej nie ma sensu, przecież powodowałoby przesuwanie wszystkich kolejnych pól struktury.

Bo to nie struktura per se tylko pakiet sieciowy. Ale nawet w API Windows występują "struktury" o zmiennym rozmiarze, gdzie np. napisy występują na samym końcu.

0

Nie miałoby sensu, gdyby nie poprzednie zmienne, które określają długość łańcucha :) Akurat Lang zawsze jest 2-znakowy, ale np. tablica Ver ma swoją długość w VerLength.

1 użytkowników online, w tym zalogowanych: 0, gości: 1