|
Языки программирования Изучаем С++, Sql, php, Lua, Python |
|
Опции темы | Поиск в этой теме | Опции просмотра |
15.04.2011, 12:16 | #1 |
Ученый
Регистрация: 19.12.2010
Сообщений: 221
Сказал(а) спасибо: 64
Поблагодарили 12 раз(а) в 9 сообщениях
Записей в дневнике: 2
|
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; } |
15.04.2011, 13:09 | #2 |
RuDB Dev
Регистрация: 01.02.2010
Адрес: localhost
Сообщений: 592
Сказал(а) спасибо: 323
Поблагодарили 283 раз(а) в 122 сообщениях
Записей в дневнике: 2
|
Это работать не будет, так как у вас для структуры с типом строка не будет правильно определятся размер, к примеру вы создали структуру, попробуйте определить размер с помощью 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. |
15.04.2011, 13:28 | #3 |
Ученый
Регистрация: 19.12.2010
Сообщений: 221
Сказал(а) спасибо: 64
Поблагодарили 12 раз(а) в 9 сообщениях
Записей в дневнике: 2
|
А как-нибудь его можно направить на путь истинный?) Просто я даже не представляю как можно вклинится в тот код, чтобы заставить его читать строку как строку)
Размер строки не известен. Чтение предполагается из WDB файлов и подобных Последний раз редактировалось HuntsMan; 15.04.2011 в 13:45. |
15.04.2011, 13:51 | #4 |
Супер-модератор
Регистрация: 07.03.2010
Сообщений: 647
Сказал(а) спасибо: 100
Поблагодарили 252 раз(а) в 123 сообщениях
|
А я вот так читаю структуры:
Код:
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(); } } |
|
|