[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