С Новым годом! Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.56/16: Рейтинг темы: голосов - 16, средняя оценка - 4.56
82 / 82 / 24
Регистрация: 30.09.2011
Сообщений: 404
Записей в блоге: 6
1

Маршалинг структур: динамическое управление размером

08.11.2012, 09:52. Показов 3057. Ответов 10
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Решил изучить как с помощью средств c# передавать структуры. Нашел способы преобразования структур в массив байт с помощью Marashal. Вот код структуры:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)]
        public struct Package
        {
            public byte pack_type;
            public byte con_status;
            public uint user_id;
            public byte user_status;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string user_name;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
            public string dest_user;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
            public byte[] buffer;
        }
Собственно вопрос. Так как мне приходится над переменными типа массив указывать их размер, чтобы можно было преобразовать к массиву байт структуру, то получается у меня структура всегда одного и того же размера. Допустим мне надо передать структуру, в которой я только заполню поле pack_type, следовательно все остальное будет пустым, но так как размеры массивов уже предопределены, я отправлю структуру, как бы полностью забитую, а это не очень выгодно, в плане передачи по сети, чем меньше размер пакета, тем лучше. Можно ли строки типа "[MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]" задавать динамически, во время формирования данных для структуры?
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
08.11.2012, 09:52
Ответы с готовыми решениями:

Маршалинг структур. Размер string
В общем начал разбираться с маршалингом структур. правда некоторые моменты непонятны. например ...

Динамическое создание строки с нужным размером
В C++ есть класс string, который прекрасно создает нужный массив сразу по размеру введенного слова....

Динамическое добавление объектов(структур)
У меня есть класс, который определен как тип...в этом классе я храню информацию о выводимом...

Динамическое размещение массива структур
В коде ниже создается массив из трех структур cs и инициализируется некими значениями. #include...

10
352 / 331 / 49
Регистрация: 12.12.2011
Сообщений: 563
08.11.2012, 14:08 2
Я пользовался примерно таким костылем
C#
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
48
49
50
51
52
53
54
55
    public static class StructureMapper
    {
        public static byte[] ToByte(TPacket packet)
        {
            int size = 2 + packet.Length;
            byte[] retVal = new byte[size];
            unsafe
            {
                fixed (byte* ptr = retVal)
                {
                    *((TPacket*)ptr) = packet;
                } 
            }
 
            return retVal;
        }
 
        public static unsafe TPacket ToStruct(byte[] data)
        {
            fixed (byte* pointer = data)
                return *(TPacket*)pointer;
        }
 
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        public unsafe struct TPacket
        {
            public byte Length;
            public byte OpCode;
            private fixed byte _data[254];
 
            public byte[] Data
            {
                get
                {
                    byte[] retVal = new byte[Length];
                    fixed (byte* ptr = retVal)
                    {
                        for (int i = 0; i < retVal.Length; i++)
                        {
                            retVal[i] = ptr[i];
                        }
                    }
                    return retVal;
                }
                set
                {
                    fixed (byte* ptr = _data)
                        for (int i = 0; i < value.Length; i++)
                        {
                            ptr[i] = value[i];
                        }
                }
            }
        }
    }
1
82 / 82 / 24
Регистрация: 30.09.2011
Сообщений: 404
Записей в блоге: 6
08.11.2012, 14:40  [ТС] 3
Yukikaze, интересный костыль) после такого явно все больше появляется желание писать на плюсах или чистом си передачу структур по сети) Но как я понимаю у меня все равно остается фиксированный массив _data[254]. Я ищу способ примерно такой:
C#
1
2
3
4
5
6
7
8
9
struct S
{
    public byte[] buffer;
}
 
//......где-то в теле метода
S.buffer = new byte[2];
byte[] bytes = StructToByte(S);
//......................................
Добавлено через 13 минут
Изначально я пытался вот таким способом переводить данные структуры в массив байт:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private byte[] StructToByteArray(packege packet)
        {
            int sizeInBytes = System.Runtime.InteropServices.Marshal.SizeOf(packet);
            Console.WriteLine("Pck size: " + sizeInBytes);
            byte[] outArray = new byte[sizeInBytes];
            MemoryStream stream = new MemoryStream();
            StreamWriter writer = new StreamWriter(stream);
            writer.Write(packet.packet_version);
            writer.Write(packet.packet_type);
            writer.Write(packet.crs32_value);
            writer.Write(packet.result_code);
            writer.Flush();
            return stream.ToArray();
        }
Он работает классно, вот только на стороне сервера не получается распознать принятые данные, точнее если взять и перевести принятые данные в строку, то я получу содержимое структуры, но ведь это надо еще по переменным упаковать....
0
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
08.11.2012, 15:32 4
если надо передавать данные неизвестного размера придется отправлять их размер вместе с ними
структуру заменить класс, сделать свое преобразование в байты и обратно по своим правилам
1
82 / 82 / 24
Регистрация: 30.09.2011
Сообщений: 404
Записей в блоге: 6
08.11.2012, 15:34  [ТС] 5
m0nax, идею понял, а по поводу

Цитата Сообщение от m0nax Посмотреть сообщение
сделать свое преобразование в байты и обратно
есть примеры? или идеи?
0
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
08.11.2012, 15:53 6
да все почти так же как в приведенном StructToByteArray, просто перед записью данных записать их размер(это же не SizeOf будет, а руками посчитать)
1
82 / 82 / 24
Регистрация: 30.09.2011
Сообщений: 404
Записей в блоге: 6
08.11.2012, 16:02  [ТС] 7
m0nax, до вот в этом то и проблема щас. Приведу примеры.
Допустим есть структура:
C#
1
2
3
4
5
6
7
public struct packege
        {
            public Int16 packet_version;
            public Int16 packet_type;
            public UInt32 crs32_value;
            public Int16 result_code;
        }
Значение её переменных:
C#
1
2
3
4
pack.packet_version = 28;
pack.packet_type = 2;
pack.crs32_value = 344912;
pack.result_code = 0;
После применения моего метода получаем на выходе, вот такую строку(массив байт):
32383233343439313230
Если отбрасывать приписанные 3-йки перед каждой цифрой то получу строку со своими значениями, остается вопрос как считать? Например. Допустим я избавился от троек, домножив каждый байт(32 - это один байт) на 0x0F, вот теперь проблема в числах. Как их растосовать по переменным, понимаю что 2-йку(тип пакета) не трудно забрать, а вот 28 как вытащить? Я все к тому что число может быть и из 3 цифр и 10, это же ведь надо как то определить. Я пытался считывать из массива байт примерно вот таким образом переменные:
C#
1
pack.packet_version = (short)IPAddress.NetworkToHostOrder(reader.ReadInt16());
Но результат был неправильный. Да он считывал первых два байта, но только как 3238, в 10-ой СС это 12856 получалось.
0
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
08.11.2012, 16:06 8
Причем тут строка?
есть структура, переводишь ее в байты и отправляешь
на другой стороне получаешь в виде байтов и конвертируешь в структуру
в каком месте тут появилась строка? вместо StreamWriter использовать BinaryWriter...
0
82 / 82 / 24
Регистрация: 30.09.2011
Сообщений: 404
Записей в блоге: 6
08.11.2012, 16:09  [ТС] 9
m0nax, под строкой я имел ввиду массив из байт)))
0
1274 / 975 / 113
Регистрация: 12.01.2010
Сообщений: 1,971
08.11.2012, 16:12 10
просто читай в том же порядке что записывал, числа всегда занимают фиксированный размер поэтому хоть там 2 хоть 3463453456 не имеет значения, это все равно 4 байта (Int) и любой BinaryReader прекрасно это прочитает
1
82 / 82 / 24
Регистрация: 30.09.2011
Сообщений: 404
Записей в блоге: 6
08.11.2012, 16:18  [ТС] 11
m0nax, Заработало) и с string тоже норм работает, не надо даже указывать размер) Спасибо за подсказки, теперь все работает как надо)
0
08.11.2012, 16:18
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
08.11.2012, 16:18
Помогаю со студенческими работами здесь

Динамическое размещение массива структур
Подскажите пожалуйста, как динамически разместить массив из нескольких структур, используя операцию...

Динамическое управление памятью
Здраствуйте! Уважаемые форумчани немогли бы вы мне помочь с вот такой вот задачей? Сформировать...

Динамическое управление памятью
Пишу процедуру на языке Ассемблера. Столкнулся с проблемой, что слишком много входных параметров,...

Динамическое управление компонентами
Пример: Есть форма1 и форма2. Форма1: Компоненты: Окно &quot;мемо&quot; для ввода числа и кнопка....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Книги и учебные ресурсы по C#
InfoMaster 08.01.2025
Базовые учебники и руководства Одной из лучших книг для начинающих является "C# 10 и . NET 6 для начинающих" Эндрю Троелсена и Филиппа Джепикса . Книга последовательно раскрывает основные концепции. . .
Что такое NullReferenceEx­­­ception и как исправить?
InfoMaster 08.01.2025
NullReferenceException - одно из самых распространенных исключений, с которым сталкиваются разработчики на C#. Это исключение возникает при попытке обратиться к членам объекта (методам, свойствам или. . .
Что такое Null Pointer Exception (NPE) и как это исправить?
InfoMaster 08.01.2025
Null Pointer Exception (NPE) - это одно из самых распространенных исключений в Java, которое возникает при попытке использовать ссылку на объект, значение которой равно null. Это исключение относится. . .
Русский язык в консоли C++
InfoMaster 08.01.2025
При разработке программ на C++ одной из частых проблем, с которой сталкиваются русскоязычные программисты, является корректное отображение кириллицы в консольных приложениях. Эта проблема особенно. . .
Telegram бот на C#
InfoMaster 08.01.2025
Разработка ботов для Telegram стала неотъемлемой частью современной экосистемы мессенджеров. C# предоставляет мощный и удобный инструментарий для создания разнообразных ботов, от простых. . .
Использование GraphQL в Go (Golang)
InfoMaster 08.01.2025
Go (Golang) является одним из наиболее популярных языков программирования, используемых для создания высокопроизводительных серверных приложений. Его архитектурные особенности и встроенные. . .
Что лучше использовать при создании класса в Java: сеттеры или конструктор?
Alexander-7 08.01.2025
Вопрос подробнее: На вопрос: «Когда одновременно создаются конструктор и сеттеры в классе – это нормально?» куратор уточнил: «Ваш класс может вообще не иметь сеттеров, а только конструктор и геттеры. . .
Как работать с GraphQL на TypeScript
InfoMaster 08.01.2025
Введение в GraphQL и TypeScript В современной разработке веб-приложений GraphQL стал мощным инструментом для создания гибких и эффективных API. В сочетании с TypeScript, эта технология. . .
Счётчик на базе сумматоров + регистров и генератора сигналов согласования.
Hrethgir 07.01.2025
Создан с целью проверки скорости асинхронной логики: ранее описанного сумматора и предополагаемых fast регистров. Регистры созданы на базе ранее описанного, предполагаемого fast триггера. То-есть. . .
Как перейти с Options API на Composition API в Vue.js
BasicMan 06.01.2025
Почему переход на Composition API актуален В мире современной веб-разработки фреймворк Vue. js продолжает эволюционировать, предлагая разработчикам все более совершенные инструменты для создания. . .
Архитектура современных процессоров
inter-admin 06.01.2025
Процессор (центральный процессор, ЦП) является основным вычислительным устройством компьютера, которое выполняет обработку данных и управляет работой всех остальных компонентов системы. Архитектура. . .
История создания реляционной модели баз данных, правила Кодда
Programming 06.01.2025
Предпосылки создания реляционной модели В конце 1960-х годов компьютерная индустрия столкнулась с серьезными проблемами в области управления данными. Существовавшие на тот момент модели данных -. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru