tklab-tud / uscxml

SCXML interpreter and transformer/compiler written in C/C++ with bindings to Java, C#, Python and Lua
Other
106 stars 54 forks source link

How to add a custom action on entry to a state in C++? #168

Closed mnambi closed 6 years ago

mnambi commented 6 years ago

I am trying to add a custom action for on entry to a state. In the Waterpump example, I see that this is done by adding a script which is then transpiled to C code. Is there a way to register a callback function with the on entry event for a particular state when loading a state machine using the interpreter in C++? If anyone has more examples using the interpreter that would be helpful as well.

Thanks, Mani

sradomski commented 6 years ago

The waterpump example uses the transpiled SCXML→ C approach. By specifying datamodel="native" in the SCXML, it will put any script content verbatim into a function of the generated C source file. Just include it after the function declaration into another C source code file.

There is another approach with interpreting the SCXML at runtime. Here, you would merely register an onentry callback and check the state's id:

uscxml::Interpreter scxml = uscxml::Interpreter::fromURL("...");
scxml.on().enterState([](const std::string& sessionId,
                         const std::string& stateName,
                         const xercesc_3_1::DOMElement* state) {
    std::cout << "Entered " << stateName << std::endl;
});

Does this answer your question?

mnambi commented 6 years ago

Yes. That is what I was looking for.

Is there a way to get the state as a xercesc_3_1::DOMElement from the uscxml::Interpreter using the state id? For e.g. if my state machine has a state called "hello", is there a function of the type: xercesc_3_1::DOMElement someclass::somefunction("hello")

sradomski commented 6 years ago

From an interpreter instance, you can get its implementation via std::shared_ptr<InterpreterImpl> getImpl() const, which in turn implements XERCESC_NS::DOMDocument* getDocument() const. That is the XML document being used for the interpreter. Given that document, you can use DOMElement* getState(const std::string& stateId, const DOMElement* root) in Predicates.cpp to get the XML element with the state.

mnambi commented 6 years ago

Thanks! That worked.