• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  // Copyright Ralf W. Grosse-Kunstleve 2002-2004. Distributed under the Boost
2  // Software License, Version 1.0. (See accompanying
3  // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4  
5  /*
6      This example shows how to make an Extension Class "pickleable".
7  
8      The world class below contains member data (secret_number) that
9      cannot be restored by any of the constructors. Therefore it is
10      necessary to provide the __getstate__/__setstate__ pair of pickle
11      interface methods.
12  
13      The object's __dict__ is included in the result of __getstate__.
14      This requires more code (compare with pickle2.cpp), but is
15      unavoidable if the object's __dict__ is not always empty.
16  
17      For more information refer to boost/libs/python/doc/pickle.html.
18   */
19  
20  #include <boost/python/module.hpp>
21  #include <boost/python/def.hpp>
22  #include <boost/python/class.hpp>
23  #include <boost/python/tuple.hpp>
24  #include <boost/python/dict.hpp>
25  #include <boost/python/extract.hpp>
26  #include <boost/python/back_reference.hpp>
27  
28  namespace boost_python_test {
29  
30    // A friendly class.
31    class world
32    {
33      public:
world(const std::string & _country)34        world(const std::string& _country) : secret_number(0) {
35          this->country = _country;
36        }
greet() const37        std::string greet() const { return "Hello from " + country + "!"; }
get_country() const38        std::string get_country() const { return country; }
set_secret_number(int number)39        void set_secret_number(int number) { secret_number = number; }
get_secret_number() const40        int get_secret_number() const { return secret_number; }
41      private:
42        std::string country;
43        int secret_number;
44    };
45  
46    struct world_pickle_suite : boost::python::pickle_suite
47    {
48      static
49      boost::python::tuple
getinitargsboost_python_test::world_pickle_suite50      getinitargs(const world& w)
51      {
52          return boost::python::make_tuple(w.get_country());
53      }
54  
55      static
56      boost::python::tuple
getstateboost_python_test::world_pickle_suite57      getstate(boost::python::object w_obj)
58      {
59          world const& w = boost::python::extract<world const&>(w_obj)();
60  
61          return boost::python::make_tuple(
62              w_obj.attr("__dict__"),
63              w.get_secret_number());
64      }
65  
66      static
67      void
setstateboost_python_test::world_pickle_suite68      setstate(boost::python::object w_obj, boost::python::tuple state)
69      {
70          using namespace boost::python;
71          world& w = extract<world&>(w_obj)();
72  
73          if (len(state) != 2)
74          {
75            PyErr_SetObject(PyExc_ValueError,
76                            ("expected 2-item tuple in call to __setstate__; got %s"
77                             % state).ptr()
78                );
79            throw_error_already_set();
80          }
81  
82          // restore the object's __dict__
83          dict d = extract<dict>(w_obj.attr("__dict__"))();
84          d.update(state[0]);
85  
86          // restore the internal state of the C++ object
87          long number = extract<long>(state[1]);
88          if (number != 42)
89              w.set_secret_number(number);
90      }
91  
getstate_manages_dictboost_python_test::world_pickle_suite92      static bool getstate_manages_dict() { return true; }
93    };
94  
95  }
96  
BOOST_PYTHON_MODULE(pickle3_ext)97  BOOST_PYTHON_MODULE(pickle3_ext)
98  {
99      using namespace boost_python_test;
100      boost::python::class_<world>(
101          "world", boost::python::init<const std::string&>())
102          .def("greet", &world::greet)
103          .def("get_secret_number", &world::get_secret_number)
104          .def("set_secret_number", &world::set_secret_number)
105          .def_pickle(world_pickle_suite())
106          ;
107  }
108