Reputation: 3487
Hi I am using python to initiate a cpp class which use boost python lib to convert into python usable. at the same time, i have a requirement to pickle the python classes that use the python enabled cpp class.
So what i did is to add enable_picking() to an example class definition like this:
class_<pform::base::Price>("Price", init<double>())
.def(self == self)
.def(self_ns::str(self_ns::self)) // __str__
.def("get_value", &pform::base::Price::get_value)
it make the class pickleable. However i get this error when unpickle it.
Boost.Python.ArgumentError: Python argument types in
Price.__init__(Price)
did not match C++ signature:
__init__(_object*, double)
So what is missing here?
Upvotes: 2
Views: 1438
Reputation: 5190
A bit late, but I found the relevant boost documentation for this:
http://www.boost.org/doc/libs/1_64_0/libs/python/doc/html/reference/topics/pickle_support.html
The Pickle Interface
At the user level, the Boost.Python pickle interface involves three special methods:
__getinitargs__
When an instance of a Boost.Python extension class is pickled, the pickler tests if the instance has a__getinitargs__
method. This method must return a Python tuple (it is most convenient to use aboost::python::tuple
). When the instance is restored by the unpickler, the contents of this tuple are used as the arguments for the class constructor. If__getinitargs__
is not defined, pickle.load will call the constructor (__init__
) without arguments; i.e., the object must be default-constructible.
__getstate__
When an instance of a Boost.Python extension class is pickled, the pickler tests if the instance has a__getstate__
method. This method should return a Python object representing the state of the instance.
__setstate__
When an instance of a Boost.Python extension class is restored by the unpickler (pickle.load), it is first constructed using the result of__getinitargs__
as arguments (see above). Subsequently the unpickler tests if the new instance has a__setstate__
method. If so, this method is called with the result of__getstate__
(a Python object) as the argument.The three special methods described above may be
.def()
'ed individually by the user. However, Boost.Python provides an easy to use high-level interface via theboost::python::pickle_suite
class that also enforces consistency:__getstate__
and__setstate__
must be defined as pairs. Use of this interface is demonstrated by the following examples.
In your particular example the class is not default constructible as it needs a double
argument (which I assume is the "value"). To wrap it for Python you would also need to define:
.def("__getinitargs__", +[](pform::base::Price const& self){
return boost::python::make_tuple(self.get_value());
})
Now Boost Python will initialize your class using "value"; instead of calling the default constructor (pform::base::Price()
).
Upvotes: 2