![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Конструкция record`а.
Riply © (2007-11-03 13:49:00)Здравствуйте !
Чем при создании (использовании) отличаются следующие два рекорда:
type
TSysRec = packed record
NextOffset: ULONG;
function MyFunct: NTSTATUS;
end;
type
TSysRec = packed record
NextOffset: ULONG;
end;
?.
Некузяво вышло.
Попробую сформулировать вопрос по-другому:
Допустим есть некий рекорд (TSysRec), с которым
работают(создают, записывают, считывают и т.п.) некие Nt-функции
и менять его размер, "структуру" нельзя ну ни на йоту.
А мне вот приспичило добавить в него свою функцию и все тут :)
Какие изменения в его внутренности внесу и чем это может быть черевато ?
vpbar (2007-11-04 18:14:00) [1]>>При использовании во втором случае можно сделать
Гы. Наоборот
vpbar (2007-11-04 18:13:00) [2]Чем при создании (использовании) отличаются следующие два рекорда:
type
TSysRec = packed record
NextOffset: ULONG;
function MyFunct: NTSTATUS;
end;
type
TSysRec = packed record
NextOffset: ULONG;
end;
При создании ни чем. Т.е. в памяти они имеют (насколько я понимаю) одинаковую структуру. При использовании во втором случае можно сделать
так
SR:TSysRec;
SR.MyFunct;
а в первом нельзя. Но можно так
function MyFunct(const value:TSysRec):NTSTATUS;
MyFunct(SR);
что по сути одно и тоже, и SR.MyFunct - просто синтаксический сахар.
Какие изменения в его внутренности внесу и чем это может быть черевато ?
Насколько я знаю, если просто добавить функцию в record то никаких изменений в его структуру это не внесет (по крайней мере в BDS2006 обратного мне не встречалось). Ибо не нужны никакие изменения.
Мне кажется, что можно выкрутиться, создав Temlate структуру,
в которой определить нужные ф-ии (с учетом Sender`а),
и в нужном месте использовать приведение рабочих ст-р к Temlate`у.
В смысле _TEMPLATE_REC(WORK_REC) ?? Нууу. А может тогда использовать packed class?
TSysRecС = packed class
NextOffset : ULONG;
DataOffset : ULONG;
DataLength : ULONG;
NameLength : ULONG;
Name : array[0..0] of WCHAR;
function MyFunct: Boolean;
end;
Для удобства. А во внешние функции возвращать указатель (PSysRec(Integer(TSysRecС)+4) или временную переменную нужного типа.
Riply (2007-11-03 21:13:00) [3]> [36] Leonid Troyanovsky © (03.11.07 20:34)
> Ну, я и намудрил :)
Ничего, я правильно поняла :)
Riply (2007-11-03 21:12:00) [4]> [35] guav © (03.11.07 20:21)
> Можно выдумать что-то вроде
......
Примерно так я и планировала, с маленькой попроавкой:
У всех структур есть простенькие ф-ии GetInfo и SetParams.
Temlate вызывает GetInfo, считает(контролирует) и преобразует все что надо,
и вызывает SetParams. Тогда можно считать, что параметры почти не нужны :)
> Вообще ты наверное не на том языке пишешь :)
> если хочешь что-то вроде [24]. Попробуй С.
Ой и не говори... Но "лошадей на переправе не меняют" ?
P.S.
Медленно, от силы по часику в день,
пытаюсь выделить на С, но это "мертвому припарки" :(
Единственное, чему научилась - не падать в обморок при виде С-шного кода :)
Leonid Troyanovsky (2007-11-03 20:34:00) [5]
> Leonid Troyanovsky © (03.11.07 20:13) [32]
> Может быть и существует способ использования регулярных
> процедур
> в качестве основы для базовых методов.
Ну, я и намудрил :)
Регулярные процедуры просто вызываются с параметром-рекордом.
Т.е., общие действия совершаются глобальными процедурами,
а специфические - методами рекордов.
--
Regards, LVT.
guav (2007-11-03 20:21:00) [6]> _TEMPLATE_REC = packed record
> ...
> ...
> // NextEntryOffest : ULONG; Пока отбросим это поле.
> DataOffset : ULONG;
> DataLength : ULONG;
> NameLength : ULONG;
> Name : array[0..0] of WCHAR;
> end;
Можно выдумать что-то вроде
type TCommonPart = packed record
DataOffset : ULONG;
DataLength : ULONG;
NameLength : ULONG;
Name : array[0..0] of WCHAR;
end;
type TSomeRec1 = packed record
...
commonPart: TCommonPart;
end;
type TSomeRec2 = packed record
...
commonPart: TCommonPart;
end;
function InitRec(var R; // сам record
sizeOfR: ULONG; // размер record
var commonPart: TCommonPart; // общая часть, д.б. внутри R и это легко сделать проверяемым.
... // можно передавать Name и Data сюда же
TCommonPart можно поместить в начало рекордов, тогда на один параметр InitRec меньше и все действия станут понятнее.
Вообще ты наверное не на том языке пишешь :) если хочешь что-то вроде [24]. Попробуй С.
> > PS: Ставлю Turbo Delphi 2006 чтобы глянуть эти новые особенности синаксиса.
> В ход пошла тяжелая артилерия ?
Я просто захотел глянуть что это за новинка - методы в рекордах.
Дело в том что если бы кроме этой фичи ничего бы не добавилось в рекорды, то сама по себе фича была бы почти бесполезна. Теперь выяснил, что там ещё добавились области видимости и свойства в рекорды, при совместном использовании всего этого можно извлечь пользу.
Riply (2007-11-03 20:18:00) [7]> [33] Riply © (03.11.07 20:15)
> то можно попробовать приступить к реализации.
P.S.
А все таки жаль, что нет "это не прерводится на человеческий язык" ф-ий :)
Riply (2007-11-03 20:15:00) [8]> [31] Leonid Troyanovsky © (03.11.07 20:01)
> Если не планируется портировать на те языки, в которых
> подобных средств нет, то почему бы и нет.
> Ясно, что это проще, т.е. позволяет избежать многих ошибок.
> Ну, а MS это, видимо, по барабану, т.к. сами структуры
> не затрагиваются.
Ну раз еще и вопрос с "нравственностью" улажен
(один голос(guav) против, два(Leonid Troyanovsky, Riply) - за),
то можно попробовать приступить к реализации. :)
Leonid Troyanovsky (2007-11-03 20:13:00) [9]
> Riply © (03.11.07 19:59) [30]
> Мне кажется, что можно выкрутиться, создав Temlate структуру,
Скорее всего методы структур устроены подобно методам классов,
и принимают неявный параметр с указателем на рекорд.
Может быть и существует способ использования регулярных процедур
в качестве основы для базовых методов.
--
Regards, LVT.
Leonid Troyanovsky (2007-11-03 20:01:00) [10]
> Riply © (03.11.07 19:51) [28]
> Осталось урегулировать вопрос с "является ли порочной"
> практика внесения своих методов в чужие (тем более Microsoft`кие)
> структуры ?
Если не планируется портировать на те языки, в которых
подобных средств нет, то почему бы и нет.
Ясно, что это проще, т.е. позволяет избежать многих ошибок.
Ну, а MS это, видимо, по барабану, т.к. сами структуры
не затрагиваются.
Только, мне кажется, что надо избегать методов-функций,
возвращающих указатель на саму структуру, чтоб
не соблазняться использованием вместо структуры.
Если все методы будут процедурами будет спокойней, IMHO.
--
Regards, LVT.
Riply (2007-11-03 19:59:00) [11]> [29] Leonid Troyanovsky © (03.11.07 19:52)
> А их в любом случае надо расписывать персонально.
>Структуры не наследуются, разные - несовместимы по присваиванию.
Мне кажется, что можно выкрутиться, создав Temlate структуру,
в которой определить нужные ф-ии (с учетом Sender`а),
и в нужном месте использовать приведение рабочих ст-р к Temlate`у.
P.S.
Это только в проекте, еще не реализовано.
Leonid Troyanovsky (2007-11-03 19:52:00) [12]
> Riply © (03.11.07 19:44) [27]
> Может плюнуть и расписывать все это хозяйство персонально
> для каждой структуры ?
А их в любом случае надо расписывать персонально.
Структуры не наследуются, разные - несовместимы по присваиванию.
--
Regards, LVT.
Riply (2007-11-03 19:51:00) [13]> [26] Leonid Troyanovsky © (03.11.07 19:25)
> и не думаю, что при описанных действиях
> проявятся какие-либо побочные эффекты.
Спасибо. Именно это меня и беспокоило.
Осталось урегулировать вопрос с "является ли порочной"
практика внесения своих методов в чужие (тем более Microsoft`кие) структуры ?
Riply (2007-11-03 19:44:00) [14]> [25] guav © (03.11.07 19:12)
> Это не функции. И даже не шаблоны. Это сишные макросы.
> Это не прерводится на человеческий язык.
Вот это ты обрадовал :)
> Уточни свою задачу, или хотя бы приведи пример с более чем одной структурой.
Конкретный пример из проекта не привести.
Слишком много вложенностей и внутренних ссылок :(
Попробую "на пальцах".
Структуры имеют примерно такой вид:
_TEMPLATE_REC = packed record
...
...
// NextEntryOffest : ULONG; Пока отбросим это поле.
DataOffset : ULONG;
DataLength : ULONG;
NameLength : ULONG;
Name : array[0..0] of WCHAR;
end;
Где:
... - разные поля в разных рекордах
DataOffset - оффсет до Data (не участвует в рекорде)
Data - следует сразу после Name плюс NameLength, выровненного до DWord.
Кроме всего прочего, надо вычислять(контролировать) DataOffset,
выравнивать полученное и получать размер структуры.
Ф-ии типа, "не прерводится на человеческий язык" сумели бы помочь :)
> PS: Ставлю Turbo Delphi 2006 чтобы глянуть эти новые особенности синаксиса.
В ход пошла тяжелая артилерия ?
А не из пушки это будет по воробъям ?
Может плюнуть и расписывать все это хозяйство персонально для каждой структуры ?
Leonid Troyanovsky (2007-11-03 19:25:00) [15]
> Riply © (03.11.07 15:30) [10]
> Но ведь должно же где-то хранится... Что-то, где-то меняется.
В самой записи, как мы убедились, ничего не хранится.
Если взять массив таких записей, можно убедиться,
что он также имеет ожидаемый размер.
Т.к., методы статические, то компилятор имеет возможность
генерировать весь необходимый код в нужных местах,
где вызываются эти методы.
Т.е., получается, что методы имеют видимость
ограниченную однотипными рекордами.
Возможно, что это именно то, что тебе хотелось,
и не думаю, что при описанных действиях
проявятся какие-либо побочные эффекты.
--
Regards, LVT.
guav (2007-11-03 19:12:00) [16]> (это можно перевести на Delpi ?):
Это не функции. И даже не шаблоны. Это сишные макросы. Это не прерводится на человеческий язык.
Только вставлять по месту. Или прикручивать препроцессор, на правах седла для коровы.
Уточни свою задачу, или хотя бы приведи пример с более чем одной структурой.
PS: Ставлю Turbo Delphi 2006 чтобы глянуть эти новые особенности синаксиса.
Riply (2007-11-03 18:57:00) [17]> [23] guav © (03.11.07 18:34)
> Полиморфизм, который ты возможно хочешь тут, реализуется через информацию о типе,
> которая бы таки заняла место в рекорде, нарушив бы "неприкасаемость".
Нарушать нельзя.
Может тогда что-то такого типа (это можно перевести на Delpi ?):
00203 /*
00204 * PURPOSE: Returns the byte offset of a field within a structure
00205 */
00206 #define FIELD_OFFSET(Type,Field) (LONG)(&(((Type *)(0))->Field))
00207
00208 /*
00209 * PURPOSE: Returns the base address structure if the caller knows the
00210 * address of a field within the structure
00211 * ARGUMENTS:
00212 * Address = address of the field
00213 * Type = Type of the whole structure
00214 * Field = Name of the field whose address is none
00215 */
00216 #define CONTAINING_RECORD(address, type, field) \
00217 ((type *)(((ULONG_PTR)address) - (ULONG_PTR)(&(((type *)0)->field))))
guav (2007-11-03 18:34:00) [18]Полиморфизм, который ты возможно хочешь тут, реализуется через информацию о типе, которая бы таки заняла место в рекорде, нарушив бы "неприкасаемость".
guav (2007-11-03 18:30:00) [19]> Было бы очень удобно определить в них некую ф-ию, которая
> занималась бы подсчетом
> всего этого безобразия и заодно проверяла бы валидность
> стр-ры.
Ты хочешь полиморфизм средствами языка тут ?
Или ты явно указывешь тип структуры - или у тебя будет одна реализация на все структуры.
Единую реализацию на все структуры лучше оформить так:
function SizeOfMe(var R);
и разумеется там так просто SizeOf(R) не получится.
Riply (2007-11-03 17:00:00) [20]> [19] guav © (03.11.07 16:28)
> Ну по мсдн можно глянуть что это
> http://msdn2.microsoft.com/en-us/library/t792xy69(VS.80).aspx
Спасибо.
> тебе нужен конкреный расклад для чтения структуры откуда-либо
> и/или передачи куда либо, не так ли ?), а методы - к реализации.
Дело вот в чем:
Есть несколько похожих структур.
Они (или их последовательность) возвращаются некими ф-ми.
Иногда мне надо их заполнить вручную в точном соответствии с
правилами заполнения, используемыми в этих ф-иях.
(Корректно заполнить поля смещений, размеров, учитывая выравневание, и т.п.).
Было бы очень удобно определить в них некую ф-ию, которая занималась бы подсчетом
всего этого безобразия и заодно проверяла бы валидность стр-ры.
Надеюсь не очень сумбурно ?