[C++-sig] Extracting and returning a c++ object from python and garbage collection
William Ladwig
wladwig at wdtinc.com
Tue Aug 19 21:16:08 CEST 2008
I'm having a problem overriding a pure C++ virtual function in python which returns an auto_ptr to a C++ type (which has been exposed to python). It looks like I am extracting the class correctly in my base class wrapper, but when the function returns to python, it throws a segmentation fault if I try to access the returned object. I suspect I have a garbage collection problem, but I'm not sure what I'm doing wrong. How do I convert an object from python to C++ and return the C++ object without it being garbage collected? Here is a sample to illustrate the problem:
C++ code:
using namespace boost::python;
// Generic Input abstract base class
class GenericInput
{
public:
// Pure virtual function to convert to the required type
std::auto_ptr<ReqInput> void convToReqFormat() = 0;
};
// Required input format
class ReqInput
{
public:
ReqInput(unsigned int rows, unsigned int cols)
: _Rows(rows),
_Cols(cols)
unsigned int getRows() const {return _Rows;}
unsigned int getCols() const {return _Cols;}
private:
unsigned int _Rows;
unsigned int _Cols;
};
// Function which converts GenericInput to ReqInput
std::auto_ptr<ReqInput> processInput(GenericInput& input)
{
return input.convToReqFormat();
}
boost python wrapping code:
struct GenericInputWrapper : GenericInput, wrapper<GenericInput>
{
GenericInputWrapper()
: GenericInput(), wrapper<GenericInput>() {}
// ********** Here is where my problem is *********************
std::auto_ptr<ReqInput> void convToReqFormat()
{
// This will return a python object of the exposed ReqInput type
override func = this->get_override("convToReqFormat");
object py_obj = func();
ReqInput& req_in = extract<ReqInput&>(py_obj);
// Testing extraction
std::cout << "Testing extraction: " << req_in.getRows();
std::cout << "," << req_in.getCols() << std::endl;
// Store in an auto_ptr
std::auto_ptr<ReqInput> r;
r.reset(&req_in);
return r;
};
BOOST_PYTHON_MODULE(_core)
{
class_<ReqInput>("ReqInput", init<unsigned int, unsigned int>)
.add_property("Rows", &ReqInput::getRows)
.add_property("Cols", &ReqInput::getCols)
class_<GenericInputWrapper, boost::noncopyable>("GenericInput", no_init)
.def("foo", pure_virtual(&GenericInput::foo))
;
def ("processInput", processInput);
}
Python test code:
import _core
class TestInput(_core.GenericInput):
def __init__(self, rows, cols):
_core.GenericInput.__init__(self)
self.Rows = rows
self.Cols = cols
def convToReqFormat(self):
return ReqInput(10,10)
>>> A = TestInput(10,10)
>>> B = processInput(A)
Testing extraction: 10,10
>>> B.Rows
Segmentation Fault
Thank you for your help,
Bill
More information about the Cplusplus-sig
mailing list