[C++-sig] Re: cPickle in extension module
Norbert Riedlin
nr at netatec.de
Mon Jun 24 10:52:47 CEST 2002
> I won't be able to devote any time to it for at least a week. Maybe
someone
> else will step forward in the meantime if you can post a *minimal*
> reproducible test case.
>
> -Dave
>
OK, I'll try to make it short:
<code>
// pickletest.cpp
#include "picklemodule.h"
#include <boost/python/detail/wrap_python.hpp>
#include <boost/python/class_builder.hpp>
#include <boost/python/objects.hpp>
PYTHON_API std::string ToScript(PyObject* msg);
PYTHON_API PyObject* FromScript(const std::string& msg);
BOOST_PYTHON_MODULE_INIT(pickletest)
{
try {
python::module_builder module("pickletest");
// pickle
module.def(&FromScript, "get_object");
module.def(&ToScript, "to_script");
}
catch(...) {
python::handle_exception(); // Deal with the exception for Python
}
}
PYTHON_API std::string ToScript(PyObject* msg)
{
return Netatec::PickleModule::Instance().Dumps(msg);
}
PYTHON_API PyObject* FromScript(const std::string& msg)
{
return Netatec::PickleModule::Instance().Loads(msg);
}
// picklemodule.h, methods inlined for brevity
namespace Netatec {
class PickleModule {
private:
PickleModuleMgr() {
PyObject* mod = PyImport_ImportModule("cPickle");
if(mod == 0) {
PyErr_SetString(PyExc_ImportError, "no module cPickle found");
throw boost::python::error_already_set();
}
m_dumps = PyObject_GetAttrString(mod, "dumps");
m_loads = PyObject_GetAttrString(mod, "loads");
Py_XDECREF(mod);
}
public:
static PickleModule& Instance() {
static PickleModule theModule;
return theModule;
}
~PickleModuleMgr() {
Py_XDECREF(m_dumps);
Py_XDECREF(m_loads);
}
std::string Dumps(PyObject* theObject) const {
const int binary = 0; // 1: binary, 0: text
PyObject* str = PyObject_CallFunction(m_dumps, "Ni",
theObject, binary);
if(str == 0) {
throw boost::python::error_already_set();
}
std::string result = PyString_AsString(str);
Py_XDECREF(str);
return result;
}
PyObject* Loads(const std::string& theString) const {
return PyObject_CallFunction(m_loads, "s", theString.c_str());
}
private:
PyObject* m_dumps;
PyObject* m_loads;
};
}
</code>
Then I compile and link the extensionmodule (BTW, Im using VC++6 an gcc
2.95.2 and (now) boost.python 1.28 ).
In python I have the folowing code:
<code>
# test.py
# A simple testclass, to show that the __del__ message for a loaded object
won't be called:
class test:
def __init__(self, p1, p2): # so we have some data to pickle
self.p1 = p1
self.p2 = p2
def __del__(self):
print "__del__-method called", self.p1, self.p2
import pickletest # the extensionmodule
def save():
t=test(1, 2)
s=pickletest.to_script(t)
open("pickled.txt", "w").write(s)
# here t.__del__() is invoked
def load():
f=open("pickled.txt", "r")
s = f.readlines()
# append all lines in f. I'm sure there is a more elegant way, but who
cares...
s1 =""
for i in s:
s1 += i
t=pickletest.get_object(s1)
# here t.__del__() is NOT invoked!!!
save()
load()
</code>
I hope the code isn't too extensive.
Thanks in advance for your help
Norbert
--
Norbert Riedlin
Tel.: +49 (0)7243-2176-24
Fax.: +49 (0)7243-2176-19
mailto:norbert.riedlin at netatec.de
netatec GmbH
Am Hardtwald 3
76275 Ettlingen
More information about the Cplusplus-sig
mailing list