Некоторое время назад я задумывался об авто генерации классов, тогда я хотел использовать xml+xslt для того чтобы генерировать описания и загрузчики объектов интерфейса. Недавно я снова вернулся к этой идее и понял что использовать связку xml+xslt очень геморно, в связи с особенностями xslt. Если делаешь однопроходный парсинг то xml файл получается очень нагроможденным. Помучившись около часа я плюнул на эту затею и начал писать код на C++. В результате за несколько часов было написано около 600 строк кода и теперь у меня есть весьма неплохой генератор.
Из вот такого файла:
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 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
[object] name Timer [includes] [include0] file me_time.h [/] [include1] file me_signal.h [/] [/] [base] [base_class0] name SceneObject inheritance public [/] [/] [public] [functions] [function0] name load type builtin define yes parents_ok all [/] [function1] name draw type builtin define no [/] [function2] name constructor type builtin define yes [/] [function3] name destructor type builtin define yes [/] [/] [slots] [slot0] name _on_new_cycle [/] [/] [/] [input_params] [param0] name repeat type bool [/] [param1] name time type float default 1.0 [/] [/] [protected] [variables] [variable0] name timer type Time [/] [/] [signals] [signal0] name time_out [signal_params] [param0] name dt type float [/] [/] [/] [/] [/] [/] |
Генерируется вот такой вот исходник:
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 56 57 58 59 60 61 62 63 64 65 66 67 |
#pragma once #include <string> #include "sceneobjectfabric.h" #include "me_time.h" #include "me_signal.h" #include "sceneobject.h" class Timer : virtual public SceneObject { public: //public slots DECLARE_SLOT(Timer, _on_new_cycle ) { return _on_new_cycle_handler(); } bool _on_new_cycle_handler(); //public functions bool load ( std::string storage_name, std::string storage_prefix, std::string scene_name, std::string object_name, FileIO::FileManager *fmanager) { Config_Interface *intf = config_get_interface ( storage_name ); if ( !intf ) { _set_error ( "Can't get config interface:" + config_error() ); return false; } bool state[1]; state[0]=SceneObject::load(storage_name, storage_prefix, scene_name, object_name, fmanager); for(int a=0;a<1; ++a) if(!state[a])return false; repeat = (intf->_get_value(storage_prefix+"Timer->repeat", "")=="true")?true:false; time = atof(intf->_get_value(storage_prefix+"Timer->time", "1.0").c_str()); _slot_map_.push_back( std::make_pair(_scene_name_ + "->" + _object_name_ + "->_on_new_cycle", &_on_new_cycle)); return real_load(storage_name, storage_prefix, scene_name, object_name, fmanager); } bool real_load ( std::string storage_name, std::string storage_prefix, std::string scene_name, std::string object_name, FileIO::FileManager *fmanager); void draw(); Timer () : SceneObject(), INIT_SLOT(Timer, this, _on_new_cycle ){} ~Timer(){} //public signals protected: //protected slots //protected functions //protected signals Signal time_out; void rise_time_out( float dt) { time_out.clear_params(); time_out.add_params(dt); time_out.rise(); } private: //private slots //private functions //private signals public: //public variables // loadable params bool repeat; float time; protected: //protected variables Time timer; private: //private variables }; extern ObjectFabric<Timer> TimerFabric; |
Таким образом сразу генерируются функции загрузки и отображения объекта (по требованию), генерируются врапперы для сигналов и слотов, которые работают с понятными параметрами а не с args->int_args, что очень сильно помогает упростить жизнь)
Благодаря такому подходу достаточно легким становится написание редактора интерфейса, который будет парсить данный файл и узнавать список параметров.
Также раньше всплывала проблема сложности определения входных параметров каждого объекта, однако при наличии файла описание всегда есть где посмотреть не ковыряясь в куче кода.
В общем один профит)