Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> правильная реализация reflection+introspection, в С/С++ путем написания плагина для GCC. 
:(
    Опции темы
xvr
Дата 2.10.2011, 11:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(boostcoder @  1.10.2011,  17:50 Найти цитируемый пост)
возникло два вопроса:
1. член offset, структуры rtti_ex_, каково должно быть его значение для типов самого верхнего уровня? т.е. тех, что не являются чьими-то членами.

Ну например -1

Цитата(boostcoder @  1.10.2011,  17:50 Найти цитируемый пост)
2. по идее, rtti_ex_, должен содержать массив типов member_type_ ? или же, rtti_ex_ должны ссылаться на другие rtti_ex_, и тип member_type_ вообще лишний?

И rtti_ex_ и member_type_ внутренние структуры, которые собственно и должен генерить компилятор. Пользователь должен работать только с функциональным интерфейсом (class_ и member_), и не иметь доступа к внутренней реализации.

Что касается массивов member_type_ в rtti_ex_, то да, там должен быть указатель на массив member'ов (для структур/классов). И в принципе member_type_ действительно может отсутствовать, т.к. сейчас он полностью перекрывается с rtti_ex_.

В принципе member_type_ должен содержать поле offset, имя и ссылку на rtti_ex_. rtti_ex_ не должен содержать offset.

Цитата(boostcoder @  1.10.2011,  17:50 Найти цитируемый пост)
еще непонятно как быть при декларации данных-членов, и декларации типов-членов, как например "name2::name3"

Для них ввести специальные сущности в enum class type_

rtti_ex_ должен описывать тип, а member_type_ - инстанс (переменную верхнего уровня, или поле в структуре (типе))

PM MAIL   Вверх
boostcoder
Дата 2.10.2011, 18:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(xvr @  2.10.2011,  11:25 Найти цитируемый пост)
Ну например -1

ага.

Цитата(xvr @  2.10.2011,  11:25 Найти цитируемый пост)
Что касается массивов member_type_ в rtti_ex_, то да, там должен быть указатель на массив member'ов (для структур/классов). И в принципе member_type_ действительно может отсутствовать, т.к. сейчас он полностью перекрывается с rtti_ex_.

понял.

Цитата(xvr @  2.10.2011,  11:25 Найти цитируемый пост)
В принципе member_type_ должен содержать поле offset, имя и ссылку на rtti_ex_. rtti_ex_ не должен содержать offset.

действительно.

Цитата(xvr @  2.10.2011,  11:25 Найти цитируемый пост)
rtti_ex_ должен описывать тип, а member_type_ - инстанс (переменную верхнего уровня, или поле в структуре (типе))

ок.

PM WWW   Вверх
boostcoder
Дата 4.10.2011, 00:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



xvr, скажите, а как быть с повторами элементов глобального массива rtti_ex_? получится так, что для каждой единицы трансляции будет сгенерен такой массив. ведь элементы в таких массивах будут в большинстве своем повторяться. я понимаю(вроде как) что код использующий массив типов rtti_ex_ этой единицы трансляции будет знать только об этом массиве, и никакие перекрестные ссылки не будут иметь место. но все же, насколько это логично, и правильно ли я размышляю?
PM WWW   Вверх
xvr
Дата 4.10.2011, 09:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(boostcoder @  4.10.2011,  00:17 Найти цитируемый пост)
xvr, скажите, а как быть с повторами элементов глобального массива rtti_ex_?

Надо бороться  smile 
Цитата(boostcoder @  4.10.2011,  00:17 Найти цитируемый пост)
что код использующий массив типов rtti_ex_ этой единицы трансляции будет знать только об этом массиве, и никакие перекрестные ссылки не будут иметь место. 

Угу. Я уже приводил пример, как с этим борются в GCC - массив создается только на этапе линковки (линкером) из содержимого специальной секции. Каждый экземпляр rtti_ex_ помещается в отдельную именованную (именем замангленного типа) виртуальную секцию, и линкер на этапе линковки выкидывает дублирующиеся элементы, а все, что осталось, помещает в массив (точнее в отдельную секцию - в GCC доступ к экземплярам rtti производится по метке с именем, а не по индексу в массиве).

PM MAIL   Вверх
boostcoder
Дата 5.10.2011, 01:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(boostcoder @  20.8.2011,  11:27 Найти цитируемый пост)
в общем, ковыряниями/тыканиями/читаниями, ничего не получается. доки мало. почти нет.
пришел к решению, дважды обрабатывать единицу трансляции. первый раз - для сбора инфы, второй - для компиляции.

отменяется. разобрался с модификацией AST из плагина. есть возможность генерить что угодно. нарукоблудил несколько кодов декларации переменных/структур/функций/методов. никаких особых сложностей нет. все даже проще чем я ожидал smile

и, оказалось, что при модификации/добавлении чего-либо в AST, оно не "портиться"(о чем я переживал), и последующие алгоритмы обработки AST схватывают абсолютно все что в нем. ведь в плагин, AST передается сразу после разбора единицы трансляции. т.е. никакие алгоритмы/оптимизаторы еще не отработали.

Это сообщение отредактировал(а) boostcoder - 5.10.2011, 01:18
PM WWW   Вверх
boostcoder
Дата 6.10.2011, 08:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



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

namespace reflectpp {

void* create(const char* name, ...) { throw std::runtime_error("error!"); }
void* clone(void* ptr) { throw std::runtime_error("error!"); }

} // namespace reflectpp


использоваться это дело будет так:
Код

struct type {};

type* t1 = reflectpp::create("type");
type* t2 = reflectpp::clone(t1);

тут, для create(), мне нужно изменить строку на такую: "new type;"
если же конструктор типа требует аргументы - заменяем так: "new type(arg1, arg2, ...);"

clone. тут мне нужно определить тип на который указывает аргумент, и сформировать такую строку: "new type(*t1);"


пока все верно?

Это сообщение отредактировал(а) boostcoder - 6.10.2011, 08:56
PM WWW   Вверх
xvr
Дата 6.10.2011, 09:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(boostcoder @  6.10.2011,  08:28 Найти цитируемый пост)
тут, для create(), мне нужно изменить строку на такую: "new type;"

Угу

Цитата(boostcoder @  6.10.2011,  08:28 Найти цитируемый пост)
если же конструктор типа требует аргументы - заменяем так: "new type(arg1, arg2, ...);"

Так, но есть одно 'но' - как задать аргументы? reflectpp::create должен иметь фиксированную сигнатуру, т.е. аргументы придется передавать массивом чего то типа VARIANT. Передавать через ... не вариант - это потребует знать тип и количество аргументов статически в момент вызова reflectpp::create, что сводит на нет всю идею рефлексии  smile 

Цитата(boostcoder @  6.10.2011,  08:28 Найти цитируемый пост)
clone. тут мне нужно определить тип на который указывает аргумент, и сформировать такую строку: "new type(*t1);"

Угу


PM MAIL   Вверх
boostcoder
Дата 6.10.2011, 12:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



xvr, я тут вот что подумал..
для создания объектов произвольного типа, в структуру rtti_ex_ нужно добавить метод(указатель на функцию?) create(). так ведь? ну и free(), за одно.

т.е. что-то типа этого:
Код


typedef void*(*create_fn)();
typedef void(*free_fn)();

struct rtti_ex_ {
   const char* name;
   const type_ type;
   const size_t size;
   const size_t align;
   create_fn create_;
   free_fn free_;
};

...

// сгенерированные функции создающая/удаляющая свой конкретный тип.
void* create_type() { return new type;}
void free_type(void* ptr) { delete static_cast<type*>(ptr); }

static const rtti_ex_ rtti_[] = {
   {"type", class_, 1, 4, &create_type, &free_type},
   { ... }
};


верно мыслю?
PM WWW   Вверх
boostcoder
Дата 6.10.2011, 12:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(boostcoder @  6.10.2011,  12:23 Найти цитируемый пост)
ну и free(), за одно.

по поводу этого не уверен.
PM WWW   Вверх
boostcoder
Дата 6.10.2011, 15:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



опишу заново свое видение всего этого добра, чтоб расставить точки где надо.

1. функция create().
возможные варианты использования:
Код

// при подобном использовании, просто создается объект указанного типа, но не помещается в карту объектов.
type1* t1 = reflectpp::create("type1");

// при подобном использовании, создается объект указанного типа и помещается в карту объектов name -> ptr
type1* t1 = reflectpp::create("object_name = type1");

карта типов нужна для:
Код

// 1. для получения уже созданного объекта
type1* t1 = reflectpp::get("object_name");

// 2. для создания клона объекта находящегося в карте. по имени объекта определяется его тип и создается новый объект инициализируемый объектом с именем object_name
// невозможно использовать clone() для объектов не находящихся в карте.
type1* t1 = reflectpp::clone("object_name");

т.е. нужна карта типа такой:
Код

std::unordered_map<size_t, void*>

где ключ - хеш сумма от имени, значение - указатель на объект.
и еще одна типа такой:
Код

std::unordered_map<void*, rtti_ex_*>

где ключ - указатель на объект, значение - указатель на rtti_ex_ этого типа.
по идее, нужна еще и третья карта, позволяющая создавать объекты типа class_ по имени типа.
еще один пример:
Код

struct type {
   void m1() {}
   int v1;
};

int main() {
   // не сохраняем в карту
   type* t1 = reflectpp::create("type");

   // сохраняем под именем "t2"
   type* t2 = reflectpp::create("t2 = type");
   std::cout << t2->v1 << std::endl;

   // вызов метода не возвращающего значения. первый аргумент(адрес возврата результата) == NULL
   reflectpp::invoke(0, "t2.m1");
   // присваивание значения переменной-члену v1
   reflectpp::invoke(0, "t2.v1", 33);
   // чтение переменной-члена v1
   int res = 0;
   reflectpp::invoke(&res, "t2.v1");

   // присваивание значения переменной-члену v1
   reflectpp::set("t2.v1", 33);
   // чтение переменной-члена v1
   int res = 0;
   reflectpp::get(&res, "t2.v1");

   // получение информации о типе по имени типа
   reflectpp::class_ ti("type");
   for ( reflect::member_const_iterator it = ti.begin(); it != ti.end(); ++it ) {
      std::cout
      << "name: " << it->name() << std::endl
      << "type: " << it->type() << std::endl
      << "size: " << it->size() << std::endl
      << "align: " << it->align() << std::endl
      << "offset: " << it->offset() << std::endl;

      if ( it->type() == reflectpp::type_::class_ ) {
         reflectpp::class_ ti(it->name());
         for ( reflect::member_const_iterator it = ti.begin(); it != ti.end(); ++it ) {
            std::cout
            << "name: " << it->name() << std::endl
            << "type: " << it->type() << std::endl
            << "size: " << it->size() << std::endl
            << "align: " << it->align() << std::endl
            << "offset: " << it->offset() << std::endl;
      }
   }

   // получение информации о типе по указателю на объект
   reflectpp::class_ ti(t1);
   for ( reflect::member_const_iterator it = ti.begin(); it != ti.end(); ++it ) {
      std::cout
      << "name: " << it->name() << std::endl
      ...

   // получение информации о типе по имени объекта находящегося в карте
   reflectpp::class_ ti("t1");
   for ( reflect::member_const_iterator it = ti.begin(); it != ti.end(); ++it ) {
      std::cout
      << "name: " << it->name() << std::endl
      ...
}


мне не нравится присутствие трех карт.
какие предложения по этому поводу?

Это сообщение отредактировал(а) boostcoder - 6.10.2011, 16:11
PM WWW   Вверх
mes
Дата 6.10.2011, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(boostcoder @  6.10.2011,  14:27 Найти цитируемый пост)
по идее, нужна еще и третья карта, позволяющая создавать объекты типа class_ по имени типа.

во первых почему создавать, во вторых зачем Вам столько карт ?   smile

во вторых Вы собрали в одну лукошко разные по сути и природе явления.. 


Это сообщение отредактировал(а) mes - 6.10.2011, 16:17


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 6.10.2011, 16:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



mes, Ваши предложения?
PM WWW   Вверх
mes
Дата 6.10.2011, 16:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



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

Цитата(boostcoder @  6.10.2011,  15:22 Найти цитируемый пост)
mes, Ваши предложения? 

трудно сказать, потому что концепция к которой Вы стремитесь не до конца ясна..

прежде всего rtti_ex предназначена для любых типов или только для классовых ?
если для всех, то вопрос, для чего может понадобиться создание объекта неполиморфного класса по имени ?!


Это сообщение отредактировал(а) mes - 6.10.2011, 16:26


--------------------
PM MAIL WWW   Вверх
boostcoder
Дата 6.10.2011, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(mes @  6.10.2011,  16:22 Найти цитируемый пост)
прежде всего rtti_ex предназначена для любых типов или только для классовых ?

для всех.

Цитата(mes @  6.10.2011,  16:22 Найти цитируемый пост)
если для всех, то вопрос, для чего может понадобиться создание объекта неполиморфного класса по имени ?!

по простому - юзер будет в терминале вводить имя.

или же так:
Код

reflectpp::script("
t1 = type1;
print t1;

if t1 == type_::class_
   for it in t1.members
      print it;
");

или так:
Код

std::ifstream file("filename");
std::string str((std::istream_iterator<char>(file)), (std::istream_iterator<char>()));

reflectpp::script(str);


Это сообщение отредактировал(а) boostcoder - 6.10.2011, 16:42
PM WWW   Вверх
mes
Дата 6.10.2011, 16:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(boostcoder @  6.10.2011,  15:33 Найти цитируемый пост)
по простому - юзер будет в терминале вводить имя.

ну создал юзер тип int  как void *  и что делать с ним дальше ?
если Вы о том что в яве и шарпе можно создавать интегральные типы, так только те что являются по сути объектами.. т.е. только полиморфные типы.. 
можно конечно преврать и простые типы в полиморфные посредством например интектуального указателя.. но опять напрашивается вопрос, что за модель у нас в конце тунеля ? или просто попытка набросать побольше фичей, без учета возможностей их иоспользования ?

Добавлено через 2 минуты и 39 секунд
Цитата(boostcoder @  6.10.2011,  15:33 Найти цитируемый пост)
reflectpp::script(str);

smile хотите загнать всю стат-информацию о типах в рантайм ?  smile 


--------------------
PM MAIL WWW   Вверх
Страницы: (10) Все « Первая ... 6 7 [8] 9 10 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0643 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.