test_pickling.cpp revision 12037
111986Sandreas.sandberg@arm.com/* 211986Sandreas.sandberg@arm.com tests/test_pickling.cpp -- pickle support 311986Sandreas.sandberg@arm.com 411986Sandreas.sandberg@arm.com Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> 511986Sandreas.sandberg@arm.com 611986Sandreas.sandberg@arm.com All rights reserved. Use of this source code is governed by a 711986Sandreas.sandberg@arm.com BSD-style license that can be found in the LICENSE file. 811986Sandreas.sandberg@arm.com*/ 911986Sandreas.sandberg@arm.com 1011986Sandreas.sandberg@arm.com#include "pybind11_tests.h" 1111986Sandreas.sandberg@arm.com 1211986Sandreas.sandberg@arm.comclass Pickleable { 1311986Sandreas.sandberg@arm.compublic: 1411986Sandreas.sandberg@arm.com Pickleable(const std::string &value) : m_value(value) { } 1511986Sandreas.sandberg@arm.com const std::string &value() const { return m_value; } 1611986Sandreas.sandberg@arm.com 1711986Sandreas.sandberg@arm.com void setExtra1(int extra1) { m_extra1 = extra1; } 1811986Sandreas.sandberg@arm.com void setExtra2(int extra2) { m_extra2 = extra2; } 1911986Sandreas.sandberg@arm.com int extra1() const { return m_extra1; } 2011986Sandreas.sandberg@arm.com int extra2() const { return m_extra2; } 2111986Sandreas.sandberg@arm.comprivate: 2211986Sandreas.sandberg@arm.com std::string m_value; 2311986Sandreas.sandberg@arm.com int m_extra1 = 0; 2411986Sandreas.sandberg@arm.com int m_extra2 = 0; 2511986Sandreas.sandberg@arm.com}; 2611986Sandreas.sandberg@arm.com 2711986Sandreas.sandberg@arm.comclass PickleableWithDict { 2811986Sandreas.sandberg@arm.compublic: 2911986Sandreas.sandberg@arm.com PickleableWithDict(const std::string &value) : value(value) { } 3011986Sandreas.sandberg@arm.com 3111986Sandreas.sandberg@arm.com std::string value; 3211986Sandreas.sandberg@arm.com int extra; 3311986Sandreas.sandberg@arm.com}; 3411986Sandreas.sandberg@arm.com 3511986Sandreas.sandberg@arm.comtest_initializer pickling([](py::module &m) { 3611986Sandreas.sandberg@arm.com py::class_<Pickleable>(m, "Pickleable") 3711986Sandreas.sandberg@arm.com .def(py::init<std::string>()) 3811986Sandreas.sandberg@arm.com .def("value", &Pickleable::value) 3911986Sandreas.sandberg@arm.com .def("extra1", &Pickleable::extra1) 4011986Sandreas.sandberg@arm.com .def("extra2", &Pickleable::extra2) 4111986Sandreas.sandberg@arm.com .def("setExtra1", &Pickleable::setExtra1) 4211986Sandreas.sandberg@arm.com .def("setExtra2", &Pickleable::setExtra2) 4311986Sandreas.sandberg@arm.com // For details on the methods below, refer to 4411986Sandreas.sandberg@arm.com // http://docs.python.org/3/library/pickle.html#pickling-class-instances 4511986Sandreas.sandberg@arm.com .def("__getstate__", [](const Pickleable &p) { 4611986Sandreas.sandberg@arm.com /* Return a tuple that fully encodes the state of the object */ 4711986Sandreas.sandberg@arm.com return py::make_tuple(p.value(), p.extra1(), p.extra2()); 4811986Sandreas.sandberg@arm.com }) 4911986Sandreas.sandberg@arm.com .def("__setstate__", [](Pickleable &p, py::tuple t) { 5011986Sandreas.sandberg@arm.com if (t.size() != 3) 5111986Sandreas.sandberg@arm.com throw std::runtime_error("Invalid state!"); 5211986Sandreas.sandberg@arm.com /* Invoke the constructor (need to use in-place version) */ 5311986Sandreas.sandberg@arm.com new (&p) Pickleable(t[0].cast<std::string>()); 5411986Sandreas.sandberg@arm.com 5511986Sandreas.sandberg@arm.com /* Assign any additional state */ 5611986Sandreas.sandberg@arm.com p.setExtra1(t[1].cast<int>()); 5711986Sandreas.sandberg@arm.com p.setExtra2(t[2].cast<int>()); 5811986Sandreas.sandberg@arm.com }); 5911986Sandreas.sandberg@arm.com 6012037Sandreas.sandberg@arm.com#if !defined(PYPY_VERSION) 6111986Sandreas.sandberg@arm.com py::class_<PickleableWithDict>(m, "PickleableWithDict", py::dynamic_attr()) 6211986Sandreas.sandberg@arm.com .def(py::init<std::string>()) 6311986Sandreas.sandberg@arm.com .def_readwrite("value", &PickleableWithDict::value) 6411986Sandreas.sandberg@arm.com .def_readwrite("extra", &PickleableWithDict::extra) 6511986Sandreas.sandberg@arm.com .def("__getstate__", [](py::object self) { 6611986Sandreas.sandberg@arm.com /* Also include __dict__ in state */ 6711986Sandreas.sandberg@arm.com return py::make_tuple(self.attr("value"), self.attr("extra"), self.attr("__dict__")); 6811986Sandreas.sandberg@arm.com }) 6911986Sandreas.sandberg@arm.com .def("__setstate__", [](py::object self, py::tuple t) { 7011986Sandreas.sandberg@arm.com if (t.size() != 3) 7111986Sandreas.sandberg@arm.com throw std::runtime_error("Invalid state!"); 7211986Sandreas.sandberg@arm.com /* Cast and construct */ 7311986Sandreas.sandberg@arm.com auto& p = self.cast<PickleableWithDict&>(); 7412037Sandreas.sandberg@arm.com new (&p) PickleableWithDict(t[0].cast<std::string>()); 7511986Sandreas.sandberg@arm.com 7611986Sandreas.sandberg@arm.com /* Assign C++ state */ 7711986Sandreas.sandberg@arm.com p.extra = t[1].cast<int>(); 7811986Sandreas.sandberg@arm.com 7911986Sandreas.sandberg@arm.com /* Assign Python state */ 8011986Sandreas.sandberg@arm.com self.attr("__dict__") = t[2]; 8111986Sandreas.sandberg@arm.com }); 8212037Sandreas.sandberg@arm.com#endif 8311986Sandreas.sandberg@arm.com}); 84