Ето няколко допълнителни метода. Никой не е с толкова обща приложимост, колкото приетия отговор, но ако вашият клас отговаря на някои (прости) изисквания, можете да направите ецване по-лесно за вашите потребители, като направите самите екземпляри (не опаковани версии) годни за ецване. Всички тези техники се използват от пакета LSST afw.
Обърнете внимание, че при премахване с помощта на двойката __getstate__
/__setstate__
, методът __init__
няма да бъде извикан, което означава, че освен ако не сте внимателни, ще имате обект, с който не можете да направите нищо ( ако продължавате да получавате NotImplementedError: Wrong number or type of arguments for overloaded function
, това е възможност). Това ни кара да използваме __reduce__
(или можете да се обадите на __init__
от __setstate__
).
Ако SWIG-ing клас Foo
, който приема аргументи на конструктора, до които имате достъп от екземпляра (напр. чрез инструменти за достъп), добавете следното към вашия интерфейс (.i
) файл:
%extend Foo {
%pythoncode {
def __reduce__(self):
# Requires matching constructor: __init__(foo, bar)
args = self.getFoo(), self.getBar()
return self.__class__, args
}
}
Ако можете да създадете вашия обект с конструктор по подразбиране и след това да го манипулирате, за да възвърнете предишното си състояние, използвайте нещо подобно:
%extend Foo {
%pythoncode {
def __getstate__(self):
args = self.getFoo(), self.getBar()
return args
def __setstate__(self, state):
# Requires empty constructor: __init__()
self.__init__()
foo, bar = state
self.setFoo(foo)
self.setBar(bar)
}
}
Като алтернатива, ако вашият клас може да направи сериализиране на двоични данни към/от паметта (напр. някакво представяне в паметта на вашия собствен дисков формат):
%include "cdata.i"
%extend Foo {
%pythoncode {
def __reduce__(self):
s = Serializer()
self.serialize(s)
size = s.getLength()
data = cdata(s.getData(), size)
return unreduceFoo, (data, size)
}
}
%pythoncode {
def unreduceFoo(data, size):
s = Serializer(size)
memmove(s.getData(), data)
return Foo(s)
}
И накрая, ако използвате boost::serialization
, използвайте този фрагмент от Sogo Mineo:
%{
#include <boost/serialization/serialization.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <sstream>
%}
%include "std_string.i"
%define %boost_picklable(cls...)
%extend cls {
std::string __getstate__()
{
std::stringstream ss;
boost::archive::binary_oarchive ar(ss);
ar << *($self);
return ss.str();
}
void __setstate_internal(std::string const& sState)
{
std::stringstream ss(sState);
boost::archive::binary_iarchive ar(ss);
ar >> *($self);
}
%pythoncode %{
def __setstate__(self, sState):
self.__init__()
self.__setstate_internal(sState)
%}
}
%enddef
%boost_picklable(Foo)
person
Paul Price
schedule
05.11.2013