[C++-sig] problem with boost::python and pickling

Jakub Zytka kubol at kormoran.net
Fri Jul 2 16:41:33 CEST 2010


On 07/02/10 15:42, Jakub Zytka wrote:

Ok, on newer boost (1.43) error message pointed the actual problem:
even for such simple dummy class some pickling support must be provided, eg.

struct dummy_pickle_suite : boost::python::pickle_suite
{
static
     boost::python::tuple
     getinitargs(const dummy& w)
     {
         return boost::python::tuple();
     }

     static
     boost::python::tuple
     getstate(const dummy& w)
     {
         using namespace boost::python;
         return boost::python::tuple();
     }

     static
     void
     setstate(dummy&, boost::python::tuple)
     {
     }
};

I was mislead by this ArgumentError...

regards,
Jakub Żytka

> I've run into some problem i do not understand. Consider following example,
> which is a slightly modified pickle2.cpp from boost's libs/python/test/:
>
> #include <boost/python/module.hpp>
> #include <boost/python/def.hpp>
> #include <boost/python/class.hpp>
> #include <boost/python/tuple.hpp>
> #include <boost/python/extract.hpp>
>
> namespace boost_python_test {
>
> struct dummy // my addition
> {
> };
> // A friendly class.
> class world
> {
> public:
> world(const std::string& country) : secret_number(0) {
> this->country = country;
> }
> world(dummy) {}; // my addition
> std::string greet() const { return "Hello from " + country + "!"; }
> std::string get_country() const { return country; }
> void set_secret_number(int number) { secret_number = number; }
> int get_secret_number() const { return secret_number; }
> private:
> std::string country;
> int secret_number;
> };
>
> struct world_pickle_suite : boost::python::pickle_suite
> {
> static
> boost::python::tuple
> getinitargs(const world& w)
> {
> using namespace boost::python;
> return make_tuple(dummy()); // change to use dummy instead of string
> }
>
> static
> boost::python::tuple
> getstate(const world& w)
> {
> using namespace boost::python;
> return make_tuple(w.get_secret_number());
> }
>
> static
> void
> setstate(world& w, boost::python::tuple state)
> {
> using namespace boost::python;
>
> boost::python::object lenRes = state.attr("__len__")(); // old boost
> int const stateLen = boost::python::extract<int>(lenRes);
> if (stateLen != 1)
> {
> PyErr_SetObject(PyExc_ValueError,
> ("expected 1-item tuple in call to __setstate__; got %s"
> % state).ptr()
> );
> throw_error_already_set();
> }
> long number = extract<long>(state[0]);
> if (number != 42)
> w.set_secret_number(number);
> }
> };
>
> }
>
> BOOST_PYTHON_MODULE(pickle2_ext)
> {
> boost::python::class_< boost_python_test::dummy>( "dummy",
> boost::python::no_init );
>
> boost::python::class_<boost_python_test::world>(
> "world", boost::python::init<boost_python_test::dummy>())
> .def( boost::python::init< std::string const & >())
> .def("greet", &boost_python_test::world::greet)
> .def("get_secret_number", &boost_python_test::world::get_secret_number)
> .def("set_secret_number", &boost_python_test::world::set_secret_number)
> .def_pickle(boost_python_test::world_pickle_suite())
> ;
> }
>
> Code is compiled with gcc41, boost 1.33.1; compile options that might be relevant:
> -pthread -fno-strict-aliasing -O0 -fno-inline -g0 -m64 -fPIC
>
> then i use follwing test:
> import pickle2_ext
> import pickle
>
> a = pickle2_ext.world("asd")
> a.set_secret_number(54)
> print a.get_secret_number()
> pickle.dump(a, open('a.p', 'w'), pickle.HIGHEST_PROTOCOL)
> r = pickle.load(open('a.p'))
> print r.get_secret_number()
>
> This test yields (python 2.4):
> 54
> Traceback (most recent call last):
> File "test.py", line 7, in ?
> r = pickle.load(open('a.p'))
> File "/usr/lib64/python2.4/pickle.py", line 1390, in load
> return Unpickler(file).load()
> File "/usr/lib64/python2.4/pickle.py", line 872, in load
> dispatch[key](self)
> File "/usr/lib64/python2.4/pickle.py", line 1153, in load_reduce
> value = func(*args)
> Boost.Python.ArgumentError: Python argument types in
> world.__init__(world, dummy)
> did not match C++ signature:
> __init__(_object*, std::string)
> __init__(_object*, boost_python_test::dummy)
>
> The original example, with std::string as a constructor parameter, works fine.
> What do i miss?
>
> regards,
> Jakub Żytka
> _______________________________________________
> Cplusplus-sig mailing list
> Cplusplus-sig at python.org
> http://mail.python.org/mailman/listinfo/cplusplus-sig



More information about the Cplusplus-sig mailing list