Lost in __setstate__() in C++ and swig

M

Martin Drautzburg

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.

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
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 *'

whereas the original object behaves well
0

Am I missing something obvious ?
 
A

Amaury Forgeot d'Arc

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

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...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,736
Latest member
AdolphBig6

Latest Threads

Top