Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  10:34[Войти] | [Зарегистрироваться]
Ответ на вопрос № 83836

30-11-2022 02:22
Добрый день!

Помогите пожалуйста, уперся в стену, не обойти:
1. Выделяю память под структуру данных типа record, заполняю выделенный блок данными.
2. Указатель на данный блок памяти него вешаю в свойство Tag компонент формы.
3. Есть два типа записей. При обработке некого события, компонент по данному указателю должен получить данные.
Проблема в том, что компонент не в курсе, запись какого типа лежит по указателю. Есть ли какой то способ методами RTTI получить информацию о типе записи, размещенной по указателю?

[+] Добавить в избранные вопросы

Отслеживать ответы на этот вопрос по RSS

Ответы:


Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

18-04-2023 12:09 | Комментарий к предыдущим ответам
Ещё хотел добавить, что для 64-битного проекта tag тоже 64-битный. Видимо, для подобных целей.

18-04-2023 12:07 | Комментарий к предыдущим ответам
Python, нет, 1-й байт - это поле структуры и есть договорённость, что значения этого поля кодируют заранее известные типы. Вроде всё должно работать.

14-03-2023 11:26 | Комментарий к предыдущим ответам
>>> Сейчас вспомнил приём, который используется в win api
Там не всё так просто. Там есть поле, которое содержит число "размер структуры". И вот по этому то размеру "знающие" определяют, есть ли в структуре новые поля. То есть тем самым гарантируется, что "старая" программа вызовет "новый" интерфейс и тот не поломает старую программу, а "новая" программа сможет вызвать "старый" интерфейс и тот просто выполнит ограниченный набор функций. Это не линукс, где чуть-чуть что-то поменялось - и ломается наглухо вся система.
>>> вытащить информацию о типе можно только "договорившись", что в первом байте
Там и так 32-разрядное число, куда надо впихнуть 64-разрядный указатель, а тут ещё предлагается "укоротить" указатель ещё на 8 бит, до 24 бит. Совести у вас нет :-)!

17-01-2023 02:55
Еще посмотрите TValue из модуля RTTI. Можно создать переменную этого типа и передать ее адрес через Tag. В обработчике же ничего не надо знать про тип уже (TValue его хранит) просто с помощью метода

procedure ExtractRawData(ABuffer: Pointer);

можно извлечь значение. Конечно не видя как там у вас реализовано  наверняка сказать нельзя, но возможно такой подход будет удобен, так как информацию о типе надо иметь только в том месте кода где вы заполняете Tag.

17-01-2023 02:18
С помощью RTTI получить информацию о типе записи, размещенной по указателю нельзя никак. Но кто вам мешает передать информацию о типе, а не только адресс?

  TMyRecInfo=record
    Addr:Pointer;
    TypeInfo:Pointer;
  end;


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

11-12-2022 01:17 | Сообщение от автора вопроса
Благодарю всех за внимание к моей проблеме!
Решил не мудрить, а разделить элементы на категории, каждой из которых присваивается свой тип записи. Таким образом я могу явно приводить нетипизированный указатель к нужному мне типу, поскольку заранее его знаю. Тем не менее, все ответы интересны для изучения и применения в будущем, когда текущий подход станет слишком сложен и не оправдан.

06-12-2022 02:48 | Комментарий к предыдущим ответам
А чем это отличается от записи с вариантами?
Принципиально ничем не отличается. Только запись с вариантами - более гибкое решение.

tag - в нашем случае нетипизированный указатель. Поэтому, наверное, вытащить информацию о типе можно только "договорившись", что в первом байте, например, закодирован тип.
А парикручивать сюда RTTI - намного более тяжелое решение, чем использование классов вместо структур.

04-12-2022 21:32
>>> Думал, что как и для классов можно из экземпляра переменной вытянуть информацию о ее типе, даже если это не класс
Из переменной, может быть, и можно. Но вы же собираетесь сохранять указатель на запись в свойстве Tag, при этом информация о типе потеряется.
Кстати, экземпляр класса в Delphi знает о своем типе именно так, что в структуре, которой является тело экземпляра класса в начале идет сигнатура типа (насколько я помню, ссылка на VMT класса). Поэтому и предложил вам самодельный аналогичный механизм для записей.

04-12-2022 10:54 | Сообщение от автора вопроса
Доброго времени суток!

Всем благодарю за внимание к моей проблеме и предложенные варианты ее решения! Насчет вариантных записей мысль интересная, как то забыл, поскольку ими в общем то крайне редко пользовался... По поводу классов, тоже выход. Но у меня по данной части программы в основном используются записи, я и решил их использовать. Думал, что как и для классов можно из экземпляра переменной вытянуть информацию о ее типе, даже если это не класс.

02-12-2022 14:24 | Комментарий к предыдущим ответам
>>> Т.е. тип один, но "знающий" юзает свои поля
А чем это отличается от записи с вариантами?

Использовать классы... если бы типов структур было много, и их многообразие постоянно увеличивалось бы, тогда было бы оправдано.
Но когда типов структур всего два... использовать классы, чтобы Дельфя сама прочитала первые 4 байта и определила по ним тип... можно, наверное, но я и сам могу их прочитать :-)

01-12-2022 20:53 | Комментарий к предыдущим ответам
Не мучайтесь. Перейдите на классы. Базовый только идентификатором типа, а все остальные его потомки со своими любыми полями. Вначале читаете указатель приведением к базовому классу, а потом исходя из идентификатора типа - приводите к нужному классу.
Генерите нужный класс, присваиваете ему нужный тип. Все.
Увеличение расхода памяти в %-ном отношении мизерное.
Скорость доступа... Да, ниже. Но Вам же не ядерным реактором управлять - наносекунды роли не играют.

30-11-2022 22:29 | Комментарий к предыдущим ответам
Сейчас вспомнил приём, который используется в win api: функции принимают параметром указатель на структуру,
но есть новые, более продвинутые, которые "знают", что в этой структуре есть новые поля, которые расположены в конце.
Т.е. тип один, но "знающий" юзает свои поля. Но это, скорее, подойдёт, если большинство полей у структур одинаковые.

30-11-2022 13:41 | Комментарий к предыдущим ответам
Мне кажется, приведение указателя к integer и хранение в Tag  - обычное дело. Скорее всего следовало бы к cardinal, но tag имеет тип integer. Однако, какая разница, нужные 32 бита присвоятся. В новый средах tag имеет "плавающий" тип, видимо для совместимости с 64 битными приложениями.
GEO описал решение, но если структуры создаются и освобождаются динамически, то можно без лишних заморочек заменить их экземплярами классов. Тогда с определением типа проблем не будет.

30-11-2022 03:02
Я не самый большой спец по использованию RTTI, но в данном случае что-то вообще невероятное. Поскольку свойство Tag имеет тип Integer, то чтобы присвоить ему указатель на запись, вы должны будете выполнить приведение типов, как-то так:

  MyComponent.Tag := Integer(@MyRecord);


Откуда вообще компонент узнает про тип записи, если вы говорите ему что это целое число? Даже если вы сможете в run-time определить тип MyRecord, всё равно надо будет как-то эту информацию сообщить компоненту.

Вариантов напрашивается два:

1. Кроме указателя на данные сохранять в компоненте ещё и тип записи (зачем вообще гемор с тэгом? выведите себе потомка из требуемого компонента, добавив поле/свойство для указателя на запись, для типа записи да хоть подо что).

2. Расширьте ваши записи, добавив в каждую из них первым полем тип записи. Тогда запись сама будет содержать информацию о своем типе.

А можно вообще использовать запись с вариантами, тогда у вас останется record одного единственного типа, содержащего две структуры:

type
  TRecordType = (rtFirstType, rtSecondType);

  TRecordData = record
    case RecordType: TRecordType of
      rtFirstType: (
        Field1_1: Word;
        Field1_2: ShortString;
        Field1_3: array[0..9] of Byte);
      rtSecondType: (
        Field2_1, Field2_2: Integer;
        Field2_3: TDateTime);
    end;

var
  R1, R2: TRecordData;

begin
  R1.RecordType := rtFirstType;
  R1.Field1_1 := 5;
  R1.Field1_2 := 'Hello, world!';
  R1.Field1_3[2] := 4;
  R2.RecordType := rtSecondType;
  R2.Field2_1 := 512;
  R2.Field2_2 := 1024;
  R2.Field2_3 := Now;


Правда, в этом случае не получится использовать поля автофинализируемых типов (длинные строки, динамические массивы и т.п.)

Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
Какой месяц идет после марта?
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
Тип сообщения:
Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Страница избранных вопросов Круглого стола.
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования