test_pickling.cpp revision 11986
112855Sgabeblack@google.com/* 212855Sgabeblack@google.com tests/test_pickling.cpp -- pickle support 312855Sgabeblack@google.com 412855Sgabeblack@google.com Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> 512855Sgabeblack@google.com 612855Sgabeblack@google.com All rights reserved. Use of this source code is governed by a 712855Sgabeblack@google.com BSD-style license that can be found in the LICENSE file. 812855Sgabeblack@google.com*/ 912855Sgabeblack@google.com 1012855Sgabeblack@google.com#include "pybind11_tests.h" 1112855Sgabeblack@google.com 1212855Sgabeblack@google.comclass Pickleable { 1312855Sgabeblack@google.compublic: 1412855Sgabeblack@google.com Pickleable(const std::string &value) : m_value(value) { } 1512855Sgabeblack@google.com const std::string &value() const { return m_value; } 1612855Sgabeblack@google.com 1712855Sgabeblack@google.com void setExtra1(int extra1) { m_extra1 = extra1; } 1812855Sgabeblack@google.com void setExtra2(int extra2) { m_extra2 = extra2; } 1912855Sgabeblack@google.com int extra1() const { return m_extra1; } 2012855Sgabeblack@google.com int extra2() const { return m_extra2; } 2112855Sgabeblack@google.comprivate: 2212855Sgabeblack@google.com std::string m_value; 2312855Sgabeblack@google.com int m_extra1 = 0; 2412855Sgabeblack@google.com int m_extra2 = 0; 2512855Sgabeblack@google.com}; 2612855Sgabeblack@google.com 2712855Sgabeblack@google.comclass PickleableWithDict { 2812855Sgabeblack@google.compublic: 2912855Sgabeblack@google.com PickleableWithDict(const std::string &value) : value(value) { } 3012855Sgabeblack@google.com 3112855Sgabeblack@google.com std::string value; 3212855Sgabeblack@google.com int extra; 3312855Sgabeblack@google.com}; 3412855Sgabeblack@google.com 3512855Sgabeblack@google.comtest_initializer pickling([](py::module &m) { 3612855Sgabeblack@google.com py::class_<Pickleable>(m, "Pickleable") 3712855Sgabeblack@google.com .def(py::init<std::string>()) 3812855Sgabeblack@google.com .def("value", &Pickleable::value) 3912855Sgabeblack@google.com .def("extra1", &Pickleable::extra1) 4012855Sgabeblack@google.com .def("extra2", &Pickleable::extra2) 4112855Sgabeblack@google.com .def("setExtra1", &Pickleable::setExtra1) 4212855Sgabeblack@google.com .def("setExtra2", &Pickleable::setExtra2) 4312855Sgabeblack@google.com // For details on the methods below, refer to 4412855Sgabeblack@google.com // http://docs.python.org/3/library/pickle.html#pickling-class-instances 4512855Sgabeblack@google.com .def("__getstate__", [](const Pickleable &p) { 4612855Sgabeblack@google.com /* Return a tuple that fully encodes the state of the object */ 4712855Sgabeblack@google.com return py::make_tuple(p.value(), p.extra1(), p.extra2()); 4812855Sgabeblack@google.com }) 4912855Sgabeblack@google.com .def("__setstate__", [](Pickleable &p, py::tuple t) { 5012855Sgabeblack@google.com if (t.size() != 3) 5112855Sgabeblack@google.com throw std::runtime_error("Invalid state!"); 5212855Sgabeblack@google.com /* Invoke the constructor (need to use in-place version) */ 5312855Sgabeblack@google.com new (&p) Pickleable(t[0].cast<std::string>()); 5412855Sgabeblack@google.com 5512855Sgabeblack@google.com /* Assign any additional state */ 5612855Sgabeblack@google.com p.setExtra1(t[1].cast<int>()); 5712855Sgabeblack@google.com p.setExtra2(t[2].cast<int>()); 5812855Sgabeblack@google.com }); 5912855Sgabeblack@google.com 6012855Sgabeblack@google.com py::class_<PickleableWithDict>(m, "PickleableWithDict", py::dynamic_attr()) 6112855Sgabeblack@google.com .def(py::init<std::string>()) 6212855Sgabeblack@google.com .def_readwrite("value", &PickleableWithDict::value) 6312855Sgabeblack@google.com .def_readwrite("extra", &PickleableWithDict::extra) 6412855Sgabeblack@google.com .def("__getstate__", [](py::object self) { 6512855Sgabeblack@google.com /* Also include __dict__ in state */ 6612855Sgabeblack@google.com return py::make_tuple(self.attr("value"), self.attr("extra"), self.attr("__dict__")); 6712855Sgabeblack@google.com }) 6812855Sgabeblack@google.com .def("__setstate__", [](py::object self, py::tuple t) { 6912855Sgabeblack@google.com if (t.size() != 3) 7012855Sgabeblack@google.com throw std::runtime_error("Invalid state!"); 7112855Sgabeblack@google.com /* Cast and construct */ 7212855Sgabeblack@google.com auto& p = self.cast<PickleableWithDict&>(); 7312855Sgabeblack@google.com new (&p) Pickleable(t[0].cast<std::string>()); 7412855Sgabeblack@google.com 7512855Sgabeblack@google.com /* Assign C++ state */ 7612855Sgabeblack@google.com p.extra = t[1].cast<int>(); 7712855Sgabeblack@google.com 7812855Sgabeblack@google.com /* Assign Python state */ 7912855Sgabeblack@google.com self.attr("__dict__") = t[2]; 8012855Sgabeblack@google.com }); 8112855Sgabeblack@google.com}); 82