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)87BOOST_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