• 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     For simplicity, the __dict__ is not included in the result of
14     __getstate__. This is not generally recommended, but a valid
15     approach if it is anticipated that the object's __dict__ will
16     always be empty. Note that safety guards are provided to catch
17     the cases where this assumption is not true.
18 
19     pickle3.cpp shows how to include the object's __dict__ in the
20     result of __getstate__.
21 
22     For more information refer to boost/libs/python/doc/pickle.html.
23  */
24 
25 #include <boost/python/module.hpp>
26 #include <boost/python/def.hpp>
27 #include <boost/python/class.hpp>
28 #include <boost/python/tuple.hpp>
29 #include <boost/python/extract.hpp>
30 
31 namespace boost_python_test {
32 
33   // A friendly class.
34   class world
35   {
36     public:
world(const std::string & _country)37       world(const std::string& _country) : secret_number(0) {
38         this->country = _country;
39       }
greet() const40       std::string greet() const { return "Hello from " + country + "!"; }
get_country() const41       std::string get_country() const { return country; }
set_secret_number(int number)42       void set_secret_number(int number) { secret_number = number; }
get_secret_number() const43       int get_secret_number() const { return secret_number; }
44     private:
45       std::string country;
46       int secret_number;
47   };
48 
49   struct world_pickle_suite : boost::python::pickle_suite
50   {
51     static
52     boost::python::tuple
getinitargsboost_python_test::world_pickle_suite53     getinitargs(const world& w)
54     {
55         return boost::python::make_tuple(w.get_country());
56     }
57 
58     static
59     boost::python::tuple
getstateboost_python_test::world_pickle_suite60     getstate(const world& w)
61     {
62         return boost::python::make_tuple(w.get_secret_number());
63     }
64 
65     static
66     void
setstateboost_python_test::world_pickle_suite67     setstate(world& w, boost::python::tuple state)
68     {
69         using namespace boost::python;
70         if (len(state) != 1)
71         {
72           PyErr_SetObject(PyExc_ValueError,
73                           ("expected 1-item tuple in call to __setstate__; got %s"
74                            % state).ptr()
75               );
76           throw_error_already_set();
77         }
78 
79         long number = extract<long>(state[0]);
80         if (number != 42)
81             w.set_secret_number(number);
82     }
83   };
84 
85 }
86 
BOOST_PYTHON_MODULE(pickle2_ext)87 BOOST_PYTHON_MODULE(pickle2_ext)
88 {
89     using namespace boost_python_test;
90     boost::python::class_<world>(
91         "world", boost::python::init<const std::string&>())
92         .def("greet", &world::greet)
93         .def("get_secret_number", &world::get_secret_number)
94         .def("set_secret_number", &world::set_secret_number)
95         .def_pickle(world_pickle_suite())
96         ;
97 }
98