Некоторое время назад я задумывался об авто генерации классов, тогда я хотел использовать 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. Both comments and pings are currently closed.

Comments are closed at this time.