Ru-MaNGOS

Вернуться   Ru-MaNGOS > Документация > Языки программирования

Важная информация

Языки программирования Изучаем С++, Sql, php, Lua, Python

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
Старый 15.04.2011, 12:16   #1
HuntsMan
Ученый
 
Аватар для HuntsMan
 
Регистрация: 19.12.2010
Сообщений: 221
Сказал(а) спасибо: 64
Поблагодарили 12 раз(а) в 9 сообщениях
Записей в дневнике: 2
HuntsMan На верном пути
По умолчанию BinaryReader и расширение ReadStruct [C#]

Немного поизучав структуры понял что это жутко удобно, и переписал большую часть кода под них. В качестве расширения для BinaryReader использовал вот эту функцию взятую вроде из кода спеллворка:
Код:
        public static T ReadStruct<T>(this BinaryReader reader) where T: struct
        {
            GCHandle handle = GCHandle.Alloc(reader.ReadBytes(Marshal.SizeOf(typeof(T))), GCHandleType.Pinned);
            T local = (T) Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
            handle.Free();
            return local;
        }
Собственно все хорошо, но появилась проблема с сишными строками. Как я понял в шарпе строки не заканчиваются нулевым байтом, поэтому Marshal.SizeOf(typeof(T)) возвращает на 1 байт меньше чем требуется. Поэтому вопрос: каким образом ему можно указать что строка сишная, и её обрабатывать например тем же расширением ReadCString()?
HuntsMan вне форума   Ответить с цитированием
Старый 15.04.2011, 13:09   #2
Konctantin
RuDB Dev
 
Аватар для Konctantin
 
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
Konctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всемKonctantin Это имя известно всем
По умолчанию

Это работать не будет, так как у вас для структуры с типом строка не будет правильно определятся размер, к примеру вы создали структуру, попробуйте определить размер с помощью Marshal.SizeOf(typeof(T)), у вас поле типа строка будет равно 4, и в соответствии с этим у вас прочитается размер струтуры без строковых полей + 4 байта, а не размер структуры + размер строки + 1
Вообще-то строка - это своего рода динамический массив char[], а чтобы получить его через неуправляемый код - надо знать его точный размер.

ЗЫ. Если известно заранее размер строки, то, можно сделать как-то так
Код:
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=20)]
public string test;
или так
Код:
[MarshalAs(UnmanagedType.ByValArray, SizeConst=20)]
public char[] test;
__________________

Последний раз редактировалось Konctantin; 15.04.2011 в 13:18.
Konctantin вне форума   Ответить с цитированием
Старый 15.04.2011, 13:28   #3
HuntsMan
Ученый
 
Аватар для HuntsMan
 
Регистрация: 19.12.2010
Сообщений: 221
Сказал(а) спасибо: 64
Поблагодарили 12 раз(а) в 9 сообщениях
Записей в дневнике: 2
HuntsMan На верном пути
По умолчанию

А как-нибудь его можно направить на путь истинный?) Просто я даже не представляю как можно вклинится в тот код, чтобы заставить его читать строку как строку)

Размер строки не известен. Чтение предполагается из WDB файлов и подобных

Последний раз редактировалось HuntsMan; 15.04.2011 в 13:45.
HuntsMan вне форума   Ответить с цитированием
Старый 15.04.2011, 13:51   #4
LordJZ
Супер-модератор
 
Аватар для LordJZ
 
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
LordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранитаLordJZ Как самоцвет среди гранита
По умолчанию

А я вот так читаю структуры:

Код:
        public StreamHandler WriteStruct<T>(T structure) where T : struct
        {
            lock (StructHelper<T>.SyncRoot)
            {
                Marshal.StructureToPtr(structure, StructHelper<T>.UnmanagedDataBank, false);
                Marshal.Copy(StructHelper<T>.UnmanagedDataBank, StructHelper<T>.ManagedDataBank, 0, StructHelper<T>.Size);
                WriteBytes(StructHelper<T>.ManagedDataBank);
            }

            return this;
        }

        public T ReadStruct<T>() where T : struct
        {
            lock (StructHelper<T>.SyncRoot)
            {
                m_stream.Read(StructHelper<T>.ManagedDataBank, 0, StructHelper<T>.Size);
                Marshal.Copy(StructHelper<T>.ManagedDataBank, 0, StructHelper<T>.UnmanagedDataBank, StructHelper<T>.Size);
                return (T)Marshal.PtrToStructure(StructHelper<T>.UnmanagedDataBank, typeof(T));
            }
        }
Код:
    internal static class StructHelper<T> where T : struct
    {
        public static int Size { get; private set; }
        public static IntPtr UnmanagedDataBank { get; private set; }
        public static byte[] ManagedDataBank { get; private set; }
        public static object SyncRoot { get; private set; }

        static StructHelper()
        {
            Size = Marshal.SizeOf(typeof(T));
            UnmanagedDataBank = Marshal.AllocHGlobal(Size);
            ManagedDataBank = new byte[Size];
            SyncRoot = new object();
        }
    }
LordJZ вне форума   Ответить с цитированием
2 пользователя(ей) сказали cпасибо:
HuntsMan (15.04.2011), Lordronn (15.04.2011)
Ответ


Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.



Текущее время: 23:59. Часовой пояс GMT +3.


ru-mangos.ru - Русское сообщество MaNGOS
Главная цель проекта MaNGOS - обучающая, поэтому разрешается использовать исходный код и собранную программу только для образовательных целей.
Вы не можете использовать MaNGOS в коммерческих целях, а также не разрешается устанавливать публичные серверы на базе MaNGOS.
Любое копирование материалов, информации в любом виде без указания источника - форума Ru-MaNGOS будет считаться нарушением авторских прав и нарушением Уголовного Кодекса РФ, ст. 146 ст. 147.
Перевод vBulletin: zCarot