Некоторое время назад я задумывался об авто генерации классов, тогда я хотел использовать xml+xslt для того чтобы генерировать описания и загрузчики объектов интерфейса. Недавно я снова вернулся к этой идее и понял что использовать связку xml+xslt очень геморно, в связи с особенностями xslt. Если делаешь однопроходный парсинг то xml файл получается очень нагроможденным. Помучившись около часа я плюнул на эту затею и начал писать код на C++. В результате за несколько часов было написано около 600 строк кода и теперь у меня есть весьма неплохой генератор.

Из вот такого файла:

 [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
     [/]
    [/]
   [/]
  [/] 
 [/]
[/]

Генерируется вот такой вот исходник:

#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, что очень сильно помогает упростить жизнь)
Благодаря такому подходу достаточно легким становится написание редактора интерфейса, который будет парсить данный файл и узнавать список параметров.
Также раньше всплывала проблема сложности определения входных параметров каждого объекта, однако при наличии файла описание всегда есть где посмотреть не ковыряясь в куче кода.
В общем один профит)

This entry was posted on Суббота, Февраль 27th, 2010 at 12:30 and is filed under MagicEngine, Новости. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

Leave a reply

Name (*)
Mail (will not be published) (*)
URI
Comment