// Copyright (C) 2013 Davis E. King (davis@dlib.net) // License: Boost Software License See LICENSE.txt for the full license. #ifndef DLIB_SERIALIZE_PiCKLE_Hh_ #define DLIB_SERIALIZE_PiCKLE_Hh_ #include <dlib/serialize.h> #include <boost/python.hpp> #include <sstream> #include <dlib/vectorstream.h> template <typename T> struct serialize_pickle : boost::python::pickle_suite { static boost::python::tuple getstate( const T& item ) { using namespace dlib; std::vector<char> buf; buf.reserve(5000); vectorstream sout(buf); serialize(item, sout); return boost::python::make_tuple(boost::python::handle<>( PyBytes_FromStringAndSize(buf.size()?&buf[0]:0, buf.size()))); } static void setstate( T& item, boost::python::tuple state ) { using namespace dlib; using namespace boost::python; if (len(state) != 1) { PyErr_SetObject(PyExc_ValueError, ("expected 1-item tuple in call to __setstate__; got %s" % state).ptr() ); throw_error_already_set(); } // We used to serialize by converting to a str but the boost.python routines for // doing this don't work in Python 3. You end up getting an error about invalid // UTF-8 encodings. So instead we access the python C interface directly and use // bytes objects. However, we keep the deserialization code that worked with str // for backwards compatibility with previously pickled files. if (extract<str>(state[0]).check()) { str data = extract<str>(state[0]); std::string temp(extract<const char*>(data), len(data)); std::istringstream sin(temp); deserialize(item, sin); } else if(PyBytes_Check(object(state[0]).ptr())) { object obj = state[0]; char* data = PyBytes_AsString(obj.ptr()); unsigned long num = PyBytes_Size(obj.ptr()); std::istringstream sin(std::string(data, num)); deserialize(item, sin); } else { throw error("Unable to unpickle, error in input file."); } } }; #endif // DLIB_SERIALIZE_PiCKLE_Hh_