Lost in __setstate__() in C++ and swig
Amaury Forgeot d'Arc
afaNOSPAM at neuf.fr
Thu Sep 13 18:24:15 EDT 2007
Hello,
Martin Drautzburg a écrit :
> I am trying to cPickle/unpickle a C++ extension class with some private
> data members. I wrote __getstate__() and __setstate__ in C++ (I have
> to, due to the private data). Pickling writes the following file:
>
> ccopy_reg
> _reconstructor
> p1
> (cpyramid
> MidiBytes
> p2
> c__builtin__
> object
> p3
> NtRp4
> (S'some unknown MidiBytes'
> I1
> I2
> I3
> tb.
>
> But when unpickling I get the following error
>
> TypeError: in method 'MidiBytes___setstate__', argument 1 of type
> 'pyramid::MidiBytes *'
>
> I debugged the swig wrapper and indeed the wrapper is called with just
> one tuple argument. No object seems to be present at the time.
>
> All the examples I've seen use python functions for __getstate__ and
> __setstate__ and it seems to me that the object itself is already there
> when __setstate__ is called.
Unpickling an object does not use the normal path for creating the
object. More precisely, the __init__ method is not called! See
http://docs.python.org/dev/library/pickle.html#pickling-and-unpickling-normal-class-instances
I suggest that you try to play with __getinitargs__ or __getnewargs__.
By calling __init__, it will give a chance to Swig to allocate the C++
object.
>
> In a moment of dispair I declared __setstate__() static and have it
> create and return a MidiBytes object.
>
> MidiBytes *MidiBytes:: __setstate__ (PyObject * aTuple) {
> return new MidiBytes();
> }
>
> Then unpickling no longer complains about "argument 1", but the
> unpickled object does not work
>
> >>> nn = cPickle.load(FILE)
> >>> nn.len()
> Traceback (most recent call last):
> File "<stdin>", line 1, in ?
> File "/usr/src/sound.d/pyramid/pyramid.py", line 618, in len
> return _pyramid.MidiBytes_len(*args)
> TypeError: in method 'MidiBytes_len', argument 1 of
> type 'pyramid::MidiBytes *'
This message is typical of a swig object whose __init__ method has not
been called. (No later than today, I forgot to call the base.__init__ in
a derived class. Maybe we should ask Swig for a better message)
See above for a hint. Hope this helps...
--
Amaury
More information about the Python-list
mailing list