Meta programming

There is a code generator that allows to create some common code by using metadata. It runs before code compilation and generate files with a name <header_name>.generated.<header_extension>. For example if you run it for a file text.h it would produce a file text.generated.h

To make a metadata for you code you can use this set of macros: * SC_CLASS - allows you to specify metadata for a class; * SC_GENERATED_BODY - macros that need to be used after SC_CLASS, because it would be replaced in during compilation time with generated declaration for this class; * SC_PROPERTY - allows to specify metadata for members of a class (including static members).

You should to specify SC_CLASS and SC_GENERATED_BODY for all child classes of ScObject

Syntax

There is a syntax rule that used for a metadata specification:

[<PropertyName> [ (<PropertyValue>, <PropertyValue>, ...) ] ], …

For example:

SC_CLASS(Agent, CmdClass("command_update_power_usage"))
SC_CLASS(CmdClass("command_generate_text_from_template"), Agent)
SC_PROPERTY(Keynode("nrel_real_energy_usage"), ForceCreate)
SC_CLASS(Agent, Event(ActionManager::msActionPeriodical, SC_EVENT_ADD_OUTPUT_ARC))

You should to use SC_CLASS and SC_GENERATED_BODY in class declaration:

class AWhoAreYouAgent : public ScAgentAction
{
 SC_CLASS(Agent, CmdClass("command_who_are_you"))
 SC_GENERATED_BODY()
};

Classes

Table of available properties of class metadata (SC_CLASS):

Property Description
Agent Parent class: ScAgent and all childs
You should always use it for all ScAgent child classes
CmdClass Determine system identifier of command class that implemented by sc-agent.
Parent class: ScAgentAction
Arguments:
  • System identifier of command class.


class AAddContentAgent : public ScAgentAction
{
 SC_CLASS(Agent, CmdClass("command_add_content"))
 SC_GENERATED_BODY()
};
    
Event Specify condition to start sc-agent implementation.

Parent class: ScAgent
Arguments:
  • ScAddr of element which will be used to subscribe for an event;
  • ScEventType type of event to subscribe.
Another words, we specify sc-element and event on it, that runs implementation of sc-agent. Possible event types:
  • SC_EVENT_ADD_OUTPUT_ARC
  • SC_EVENT_ADD_INPUT_ARC
  • SC_EVENT_REMOVE_OUTPUT_ARC
  • SC_EVENT_REMOVE_INPUT_ARC
  • SC_EVENT_REMOVE_ELEMENT
  • SC_EVENT_CONTENT_CHANGED


class ANewPeriodicalActionAgent : public ScAgent
{
 SC_CLASS(Agent, Event(msActionPeriodical, SC_EVENT_ADD_OUTPUT_ARC))
 SC_GENERATED_BODY()
};
      
LoadOrder Specify order (priority) of module loading. Can be used just in ScModule child classes.
Parent class: ScModule
Arguments:
  • Priority as unsigned int number
System loads modules by ascending order. If two module has an equal load order, then they can load in any order (relative to each other).

class nlModule : public ScModule
{
 SC_CLASS(LoadOrder(11))
 SC_GENERATED_BODY()

 sc_result initializeImpl();
 sc_result shutdownImpl();
};
      

Members

Table of available properties of class members metadata (SC_PROPERTY):

Property Description
Keynode Arguments:
  • String with system identifier of sc-element.
Specify that this member is a keynode. After module starts, this member will contains ScAddr of specified sc-element or invalid ScAddr if sc-element not found. Just add ForceCreate to create sc-element in case when it didn't found.
You can use this property just for members that has ScAddr type.

SC_PROPERTY(Keynode("device"), ForceCreate)
static ScAddr m_device;
      
Template Arguments:
  • String system identifier of template sc-structure in sc-memory
Specify that this member is a template. After module starts, this template will be parsed from sc-memory. So you will be able use it to search/generate constructions.
You can use this property just for members that has ScTemplate type.

SC_PROPERTY(Template("test_template"))
ScTemplate m_testTemplate;
      
ForceCreate Arguments:
  • [optional] type of sc-element. Any value from ScType::Node...

Used just with Keynode property. Using of this property force sc-element creation, if it didn't found by system identifier.

SC_PROPERTY(Keynode("device"), ForceCreate(ScType::NodeConstClass))
static ScAddr m_device;

SC_PROPERTY(Keynode("device"), ForceCreate) // default value ScType::Node static ScAddr m_node;

FAQ

  1. How to include one MyObject into OtherObject
    /* In CPP file you should include header file for object, that implemented in this file
     * For example in file MyObject.cpp we should make order
     */
    #include "otherObject.hpp"
    #include "otherObject2.hpp"
    ...
    
    #include "myObject.hpp"
    
    // other includes (that doesn't contains ScObject derived classes)
    ...
    
    // Implementation
    ...