You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							81 lines
						
					
					
						
							2.8 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							81 lines
						
					
					
						
							2.8 KiB
						
					
					
				
								/*
							 | 
						|
								    tests/test_pickling.cpp -- pickle support
							 | 
						|
								
							 | 
						|
								    Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
							 | 
						|
								
							 | 
						|
								    All rights reserved. Use of this source code is governed by a
							 | 
						|
								    BSD-style license that can be found in the LICENSE file.
							 | 
						|
								*/
							 | 
						|
								
							 | 
						|
								#include "pybind11_tests.h"
							 | 
						|
								
							 | 
						|
								class Pickleable {
							 | 
						|
								public:
							 | 
						|
								    Pickleable(const std::string &value) : m_value(value) { }
							 | 
						|
								    const std::string &value() const { return m_value; }
							 | 
						|
								
							 | 
						|
								    void setExtra1(int extra1) { m_extra1 = extra1; }
							 | 
						|
								    void setExtra2(int extra2) { m_extra2 = extra2; }
							 | 
						|
								    int extra1() const { return m_extra1; }
							 | 
						|
								    int extra2() const { return m_extra2; }
							 | 
						|
								private:
							 | 
						|
								    std::string m_value;
							 | 
						|
								    int m_extra1 = 0;
							 | 
						|
								    int m_extra2 = 0;
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								class PickleableWithDict {
							 | 
						|
								public:
							 | 
						|
								    PickleableWithDict(const std::string &value) : value(value) { }
							 | 
						|
								
							 | 
						|
								    std::string value;
							 | 
						|
								    int extra;
							 | 
						|
								};
							 | 
						|
								
							 | 
						|
								test_initializer pickling([](py::module &m) {
							 | 
						|
								    py::class_<Pickleable>(m, "Pickleable")
							 | 
						|
								        .def(py::init<std::string>())
							 | 
						|
								        .def("value", &Pickleable::value)
							 | 
						|
								        .def("extra1", &Pickleable::extra1)
							 | 
						|
								        .def("extra2", &Pickleable::extra2)
							 | 
						|
								        .def("setExtra1", &Pickleable::setExtra1)
							 | 
						|
								        .def("setExtra2", &Pickleable::setExtra2)
							 | 
						|
								        // For details on the methods below, refer to
							 | 
						|
								        // http://docs.python.org/3/library/pickle.html#pickling-class-instances
							 | 
						|
								        .def("__getstate__", [](const Pickleable &p) {
							 | 
						|
								            /* Return a tuple that fully encodes the state of the object */
							 | 
						|
								            return py::make_tuple(p.value(), p.extra1(), p.extra2());
							 | 
						|
								        })
							 | 
						|
								        .def("__setstate__", [](Pickleable &p, py::tuple t) {
							 | 
						|
								            if (t.size() != 3)
							 | 
						|
								                throw std::runtime_error("Invalid state!");
							 | 
						|
								            /* Invoke the constructor (need to use in-place version) */
							 | 
						|
								            new (&p) Pickleable(t[0].cast<std::string>());
							 | 
						|
								
							 | 
						|
								            /* Assign any additional state */
							 | 
						|
								            p.setExtra1(t[1].cast<int>());
							 | 
						|
								            p.setExtra2(t[2].cast<int>());
							 | 
						|
								        });
							 | 
						|
								
							 | 
						|
								    py::class_<PickleableWithDict>(m, "PickleableWithDict", py::dynamic_attr())
							 | 
						|
								        .def(py::init<std::string>())
							 | 
						|
								        .def_readwrite("value", &PickleableWithDict::value)
							 | 
						|
								        .def_readwrite("extra", &PickleableWithDict::extra)
							 | 
						|
								        .def("__getstate__", [](py::object self) {
							 | 
						|
								            /* Also include __dict__ in state */
							 | 
						|
								            return py::make_tuple(self.attr("value"), self.attr("extra"), self.attr("__dict__"));
							 | 
						|
								        })
							 | 
						|
								        .def("__setstate__", [](py::object self, py::tuple t) {
							 | 
						|
								            if (t.size() != 3)
							 | 
						|
								                throw std::runtime_error("Invalid state!");
							 | 
						|
								            /* Cast and construct */
							 | 
						|
								            auto& p = self.cast<PickleableWithDict&>();
							 | 
						|
								            new (&p) Pickleable(t[0].cast<std::string>());
							 | 
						|
								
							 | 
						|
								            /* Assign C++ state */
							 | 
						|
								            p.extra = t[1].cast<int>();
							 | 
						|
								
							 | 
						|
								            /* Assign Python state */
							 | 
						|
								            self.attr("__dict__") = t[2];
							 | 
						|
								        });
							 | 
						|
								});
							 |