It is often necessary to save and restore the contents of an object to a file. One approach to this problem is to write a pair of functions that read and write data from a file in a special format. A powerful alternative approach is to use Python's pickle module. Exploiting Python's ability for introspection, the pickle module recursively converts nearly arbitrary Python objects into a stream of bytes that can be written to a file.
The Boost Python Library supports the pickle module by emulating the interface implemented by Jim Fulton's ExtensionClass module that is included in the ZOPE distribution. This interface is similar to that for regular Python classes as described in detail in the Python Library Reference for pickle.
If __getinitargs__ is not defined, the class constructor will be called without arguments.
If __getstate__ is not defined, the instance's __dict__ is pickled (if it is not empty).
If __setstate__ is not defined, the result of __getstate__ must be a Python dictionary. The items of this dictionary are added to the instance's __dict__.
However, most C++ classes wrapped with Boost.Python will have member data that are not restored correctly by this procedure. To alert the user to this problem, a safety guard is provided. If both __getinitargs__ and __getstate__ are not defined, Boost.Python tests if the class has an attribute __dict_defines_state__. An exception is raised if this attribute is not defined:
RuntimeError: Incomplete pickle support (__dict_defines_state__ not set)
In the rare cases where this is not the desired behavior, the safety
guard can deliberately be disabled. The corresponding C++ code for
this is, e.g.:
class_builder<your_class> py_your_class(your_module, "your_class");
py_your_class.dict_defines_state();
It is also possible to override the safety guard at the Python level.
E.g.:
import your_bpl_module
class your_class(your_bpl_module.your_class):
__dict_defines_state__ = 1
To alert the user to this highly unobvious problem, a safety guard is provided. If __getstate__ is defined and the instance's __dict__ is not empty, Boost.Python tests if the class has an attribute __getstate_manages_dict__. An exception is raised if this attribute is not defined:
RuntimeError: Incomplete pickle support (__getstate_manages_dict__ not set)
To resolve this problem, it should first be established that the
__getstate__ and __setstate__ methods manage the instances's __dict__
correctly. Note that this can be done both at the C++ and the Python
level. Finally, the safety guard should intentionally be overridden.
E.g. in C++:
class_builder<your_class> py_your_class(your_module, "your_class");
py_your_class.getstate_manages_dict();
In Python:
import your_bpl_module
class your_class(your_bpl_module.your_class):
__getstate_manages_dict__ = 1
def __getstate__(self):
# your code here
def __setstate__(self, state):
# your code here