1 #ifndef PYKEP_UTILS_H
2 #define PYKEP_UTILS_H
3
4 #include <Python.h>
5 #include <boost/archive/text_iarchive.hpp>
6 #include <boost/archive/text_oarchive.hpp>
7 #include <boost/python/class.hpp>
8 #include <boost/python/dict.hpp>
9 #include <boost/python/docstring_options.hpp>
10 #include <boost/python/extract.hpp>
11 #include <boost/python/tuple.hpp>
12 #include <boost/serialization/serialization.hpp>
13 #include <sstream>
14 #include <string>
15
16 template <class T>
Py_copy_from_ctor(const T & x)17 inline T Py_copy_from_ctor(const T &x)
18 {
19 return T(x);
20 }
21
22 template <class T>
Py_deepcopy_from_ctor(const T & x,boost::python::dict)23 inline T Py_deepcopy_from_ctor(const T &x, boost::python::dict)
24 {
25 return T(x);
26 }
27
28 // Generic pickle suite for C++ classes with default constructor extensible from Python.
29 // We need to take care of handling the derived class' dict.
30 // And we need to define the serialize member for the boost::python::wrapper class
31
32 // Serialization for python wrapper.
33 namespace boost
34 {
35 namespace serialization
36 {
37 template <class Archive, class T>
serialize(Archive &,boost::python::wrapper<T> &,const unsigned int)38 void serialize(Archive &, boost::python::wrapper<T> &, const unsigned int)
39 {
40 }
41 }
42 }
43
44 template <class T>
45 struct python_class_pickle_suite : boost::python::pickle_suite {
getinitargspython_class_pickle_suite46 static boost::python::tuple getinitargs(const T &)
47 {
48 return boost::python::make_tuple();
49 }
getstatepython_class_pickle_suite50 static boost::python::tuple getstate(boost::python::object obj)
51 {
52 T const &x = boost::python::extract<T const &>(obj)();
53 std::stringstream ss;
54 boost::archive::text_oarchive oa(ss);
55 oa << x;
56 return boost::python::make_tuple(obj.attr("__dict__"), ss.str());
57 }
setstatepython_class_pickle_suite58 static void setstate(boost::python::object obj, boost::python::tuple state)
59 {
60 using namespace boost::python;
61 T &x = extract<T &>(obj)();
62 if (len(state) != 2) {
63 PyErr_SetObject(PyExc_ValueError, ("expected 2-item tuple in call to __setstate__; got %s" % state).ptr());
64 throw_error_already_set();
65 }
66 // Restore the object's __dict__.
67 dict d = extract<dict>(obj.attr("__dict__"))();
68 d.update(state[0]);
69 // Restore the internal state of the C++ object.
70 const std::string str = extract<std::string>(state[1]);
71 std::stringstream ss(str);
72 boost::archive::text_iarchive ia(ss);
73 ia >> x;
74 }
getstate_manages_dictpython_class_pickle_suite75 static bool getstate_manages_dict()
76 {
77 return true;
78 }
79 };
80
81 template <class T>
py_cpp_loads(T & x,const std::string & s)82 inline void py_cpp_loads(T &x, const std::string &s)
83 {
84 std::stringstream ss(s);
85 boost::archive::text_iarchive ia(ss);
86 ia >> x;
87 }
88
89 template <class T>
py_cpp_dumps(const T & x)90 inline std::string py_cpp_dumps(const T &x)
91 {
92 std::stringstream ss;
93 boost::archive::text_oarchive oa(ss);
94 oa << x;
95 return ss.str();
96 }
97
98 #endif // PYKEP_UTILS_H
99