【问题标题】:How to Use boost msm combined with boost signal?如何将 boost msm 与 boost 信号结合使用?
【发布时间】:2018-10-12 05:47:51
【问题描述】:

我对“boost msm”真的很陌生,现在我遇到了一个问题,如何在boost msm中使用boost信号,我尝试了很多次但没有用。

我想要实现的是当机器改变状态时,动作操作符发出信号,我的外部实体捕获信号并执行其他功能,但现在我无法将信号发出机器,我可以'不要将信号与外部实体连接起来。 有例子吗?

【问题讨论】:

    标签: c++ boost boost-msm


    【解决方案1】:

    您可以结合使用 Boost.Signals2 和 Boost.MSM。

    这是简单的信号2示例。

    https://wandbox.org/permlink/XZzGIIVWXjvOPzdd(运行演示)

    #include <iostream>
    #include <string>
    
    #include <boost/signals2/signal.hpp>
    #include <iostream>
    
    // begin -- signals2 code
    struct signal_data {
        int i;
        std::string str;
    };
    
    struct sender {
        boost::signals2::signal<void(signal_data const&)> foo;
    
        void send() {
            foo(signal_data {42, "ABC"} );
        }
    };
    
    struct receiver_1 {
        void on_foo(signal_data const& sd) {
            std::cout << __PRETTY_FUNCTION__ << " " << sd.i << ", " << sd.str << std::endl;
        }
    };
    
    struct receiver_2 {
        void on_foo(signal_data const& sd) {
            std::cout << __PRETTY_FUNCTION__ << " " << sd.i << ", " << sd.str << std::endl;
        }
    };
    
    // end -- signals2 code
    
    int main() {
        // signals setup ----------------------------------------
        // external entities
        receiver_1 r1;
        receiver_2 r2;
    
        sender s;
    
        // make connection
        // using lambda expression
        s.foo.connect(
            [&] (signal_data const& param) {
                r1.on_foo(param);
            }
        );
        // or bind
        s.foo.connect(std::bind(&receiver_2::on_foo, &r2, std::placeholders::_1));
        s.send();
    }
    

    信号发送点为s.send()。如果我们可以从 msm 的 action 中调用s.send(),就可以实现目标。

    这是一个简单的 msm 示例。

    https://wandbox.org/permlink/tnRSQ07anNe49GpO(运行演示)

    #include <iostream>
    #include <string>
    
    #include <boost/msm/back/state_machine.hpp>
    
    #include <boost/msm/front/state_machine_def.hpp>
    #include <boost/msm/front/functor_row.hpp>
    
    // begin -- msm code
    namespace msm = boost::msm;
    namespace msmf = boost::msm::front;
    namespace mpl = boost::mpl;
    
    // ----- Events
    struct event1 {};
    
    // ----- State machine
    struct sm1_:msmf::state_machine_def<sm1_> {
        // States
        struct state1:msmf::state<> {};
    
        // Set initial state
        using initial_state = state1;
    
        // Actions
        struct action {
            template <class Event, class Fsm, class SourceState, class TargetState>
            void operator()(Event const&, Fsm&, SourceState&, TargetState&) const {
                std::cout << "action()" << std::endl;
                // want to call s.send() here
            }
        };
    
        // Transition table
        struct transition_table:mpl::vector<
            //          Start   Event   Next        Action      Guard
            msmf::Row < state1, event1, msmf::none, action,     msmf::none >
        > {};
    };
    
    // Pick a back-end
    using sm1 = msm::back::state_machine<sm1_>;
    
    // end -- msm code
    
    int main() {
        sm1 s1;
    
        s1.start(); 
        std::cout << "Send event1" << std::endl;
        s1.process_event(event1());
    }
    

    动作定义如下:

        struct action {
            template <class Event, class Fsm, class SourceState, class TargetState>
            void operator()(Event const&, Fsm&, SourceState&, TargetState&) const {
                std::cout << "action()" << std::endl;
                // want to call s.send() here
            }
        };
    

    如何在action中调用s.send()

    首先,将sender的引用添加为sm1_的成员变量。

    sender& s; // define sender reference as a member variable
    

    然后,在构造函数中初始化它。

    sm1_(sender& s):s(s) {} // initialize sender in constructor
    

    然后,在创建状态机时传递std::refwrapped sender。

    sm1 s1(std::ref(s)); // pass sender as reference
    

    最后,在操作中调用s.send()。您可以通过Fsm参考访问s,如下所示:

    struct action {
        template <class Event, class Fsm, class SourceState, class TargetState>
        void operator()(Event const&, Fsm& f, SourceState&, TargetState&) const {
            std::cout << "action()" << std::endl;
            f.s.send();
        }
    };
    

    这是完整的代码:

    https://wandbox.org/permlink/gh83EW8eado5iOi8(运行演示)

    #include <iostream>
    #include <string>
    
    #include <boost/signals2/signal.hpp>
    #include <iostream>
    #include <boost/msm/back/state_machine.hpp>
    
    #include <boost/msm/front/state_machine_def.hpp>
    #include <boost/msm/front/functor_row.hpp>
    
    // begin -- signals2 code
    struct signal_data {
        int i;
        std::string str;
    };
    
    struct sender {
        boost::signals2::signal<void(signal_data const&)> foo;
    
        void send() {
            foo(signal_data {42, "ABC"} );
        }
    };
    
    struct receiver_1 {
        void on_foo(signal_data const& sd) {
            std::cout << __PRETTY_FUNCTION__ << " " << sd.i << ", " << sd.str << std::endl;
        }
    };
    
    struct receiver_2 {
        void on_foo(signal_data const& sd) {
            std::cout << __PRETTY_FUNCTION__ << " " << sd.i << ", " << sd.str << std::endl;
        }
    };
    
    // end -- signals2 code
    
    // begin -- msm code
    namespace msm = boost::msm;
    namespace msmf = boost::msm::front;
    namespace mpl = boost::mpl;
    
    // ----- Events
    struct event1 {};
    
    // ----- State machine
    struct sm1_:msmf::state_machine_def<sm1_> {
        sm1_(sender& s):s(s) {} // initialize sender in constructor
    
        // States
        struct state1:msmf::state<> {};
    
        // Set initial state
        using initial_state = state1;
    
        // Actions
        struct action {
            template <class Event, class Fsm, class SourceState, class TargetState>
            void operator()(Event const&, Fsm& f, SourceState&, TargetState&) const {
                std::cout << "action()" << std::endl;
                f.s.send();
            }
        };
    
        // Transition table
        struct transition_table:mpl::vector<
            //          Start   Event   Next        Action      Guard
            msmf::Row < state1, event1, msmf::none, action,     msmf::none >
        > {};
    
        sender& s; // define sender reference as a member variable
    };
    
    // Pick a back-end
    using sm1 = msm::back::state_machine<sm1_>;
    
    // end -- msm code
    
    int main() {
        // signals setup ----------------------------------------
        // external entities
        receiver_1 r1;
        receiver_2 r2;
    
        sender s;
    
        // make connection
        // using lambda expression
        s.foo.connect(
            [&] (signal_data const& param) {
                r1.on_foo(param);
            }
        );
        // or bind
        s.foo.connect(std::bind(&receiver_2::on_foo, &r2, std::placeholders::_1));
    
        // msm setup and process ---------------------------------
        sm1 s1(std::ref(s)); // pass sender as reference
    
        s1.start(); 
        std::cout << "Send event1" << std::endl;
        s1.process_event(event1());
    }
    

    【讨论】:

      猜你喜欢
      • 2019-12-19
      • 1970-01-01
      • 2014-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多