Serialization: Create From Python, Load/Execute From Pure C++

To allow such things as saving the state of a plasm, or network transport between cells, ecto supports boost::serialization of tendrils,cells, and plasms.

Steps to ensure your types can be serialized:
  1. Write boost serialization methods for your types, don’t worry all the basic types should work by default.
  2. Use the ECTO_REGISTER_SERIALIZERS in one of your translation units.
ECTO_REGISTER_SERIALIZERS(Type)

Sample:

#include <ecto/ecto.hpp>
struct Point
{
  float x,y,z,n;
  template<typename Archive>
  void serialize(Archive& ar, const unsigned int version)
  {
    ar & x & y & z & n;
  }
};

ECTO_REGISTER_SERIALIZERS(Point);
//... more ecto code.

Embedding ecto in a c++ program

Assuming you have serializers for all your types, you may reliably serialize a graph from python and execute in a native cpp main.

Now that we have some ecto cells, like the ones in hello_ecto, we can write a python script that serializes the plasm to a text file.

#!/usr/bin/env python
import ecto #ecto core library
import ecto.hello_ecto as hello_ecto #a user library, that has a few ecto modules

plasm = ecto.Plasm()
r = hello_ecto.Reader()
p1 = hello_ecto.Printer(str="default")
p2 = hello_ecto.Printer(str="default")
plasm.connect(
              r["output"] >> (p1["str"],p2["str"])
              )

if __name__ == '__main__':
    plasm.save('printy.plasm')

Our graph is the following:

digraph G {
graph [rankdir=TB, ranksep=1]
edge [labelfontsize=8]
node [shape=plaintext]
0[label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">  <TR> <TD ROWSPAN="1" COLSPAN="1" BGCOLOR="khaki">hello_ecto::Reader</TD>  </TR>  <TR>
<TD PORT="o_output" BGCOLOR="indianred1">output</TD>
</TR> </TABLE>>];
1[label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4"> <TR>
<TD PORT="i_str" BGCOLOR="springgreen">str</TD>
</TR> <TR> <TD ROWSPAN="1" COLSPAN="1" BGCOLOR="khaki">hello_ecto::Printer</TD> <TD PORT="p_str" BGCOLOR="lightblue">str</TD>
 </TR>   </TABLE>>];
2[label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4"> <TR>
<TD PORT="i_str" BGCOLOR="springgreen">str</TD>
</TR> <TR> <TD ROWSPAN="1" COLSPAN="1" BGCOLOR="khaki">hello_ecto::Printer</TD> <TD PORT="p_str" BGCOLOR="lightblue">str</TD>
 </TR>   </TABLE>>];
0->1 [headport="i_str" tailport="o_output"];
0->2 [headport="i_str" tailport="o_output"];
}

Then a cpp file that can execute our printy.plasm file might look like:

#include <ecto/ecto.hpp>
#include <ecto/serialization/registry.hpp>
#include <ecto/serialization/cell.hpp>
#include <ecto/serialization/plasm.hpp>

#include <ecto/scheduler.hpp>

int
main()
{
  ecto::plasm::ptr p(new ecto::plasm());
  //load up our plasm
  {
    std::ifstream in("printy.plasm");
    p->load(in);
  }

  //lets make some graphviz
  {
    std::ofstream graphviz("printy.plasm.dot");
    p->viz(graphviz);
  }

  //iterate over all cells in the plasm.
  std::cout << "** cell listing" << std::endl;
  std::vector<ecto::cell::ptr> cells = p->cells();
  for (size_t i = 0; i < cells.size(); i++)
  {
    std::cout << cells[i]->name() << std::endl;
  }

  //use a scheduler...
  ecto::scheduler sched(p);
  return sched.execute();
}

The cmake for this looks like:

# 
# Copyright (c) 2011, Willow Garage, Inc.
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#     * Redistributions of source code must retain the above copyright
#       notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above copyright
#       notice, this list of conditions and the following disclaimer in the
#       documentation and/or other materials provided with the distribution.
#     * Neither the name of the Willow Garage, Inc. nor the names of its
#       contributors may be used to endorse or promote products derived from
#       this software without specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# 
add_executable(tutorial_native_plasm
  native_plasm.cpp
  )

target_link_libraries(tutorial_native_plasm
  ecto
  ${catkin_LIBRARIES}
  hello_ecto_ectomodule #uses cells from this module.
  ${CMAKE_THREAD_LIBS_INIT}
)

Running command like the following:

% ./serialize_plasm.py
% export PATH=PATH_TO_BIN:$PATH
% tutorial_native_plasm

Yields this output:

** cell listing
hello_ecto::Printer
hello_ecto::Printer
hello_ecto::Reader
h ello o q
h
h
ello
ello
o
o