6

I'm using Boost.Python to create a wrapper for my C++ library, and I'm having some troubles, googling all the day did not produc any results. For example, I have the following code:

class Base
{
public:
    virtual void func() = 0;
};

class Derived : public Base
{
public:
    virtual void func()
    {
        cout << "Derived::func()"<< endl;
    }
};


// wrapper for Base
struct BaseWrapper : Base, python::wrapper<Base>
{
    virtual void func()
    {
        this->get_override("func");
    }
};


Base* makeDerived()
{
    return new Derived;
}

vector<Base*>* makeDerivedVec()
{
    vector<Base*> *v = new vector<Base*>;
    v->push_back(new Derived);
    v->push_back(new Derived);
    v->push_back(new Derived);
    return v;
}

BOOST_PYTHON_MODULE(mylib)
{
    // export Base
    class_<BaseWrapper, noncopyable>("Base")
            .def("func", pure_virtual(&Base::func));

    class_<vector<Base*> >("BasePtrVec")
            .def(vector_indexing_suite<vector<Base*> >());

    // export Derived
    class_<Derived, bases<Base> >("Derived")
            .def("func", &Derived::func);

    // export makeDerived()
    def("makeDerived", &makeDerived, return_value_policy<manage_new_object>());

    // export makeDerivedVec()
    def("makeDerivedVec", &makeDerivedVec, return_value_policy<manage_new_object>());
}

So, I compile it, import in python and try this:

b = mylib.Base() b.func()

d = mylib.makeDerived() d.func()

The first line, as expected, throws an exception saying that b.func() is pure virtual, and the second line prints out

Derived::func()

And that's ok.

But the code

dlist = mylib.makeDerivedVec()
for d in dlist:
    d.func()

does not work, and Python throws an exception:

TypeError: No to_python (by-value) converter found for C++ type: Base*

Why it handled correctly the Base* returned by makeDerived() and refuses to work with Base* contained in std::vector? How can I make it work?

1 Answer 1

3

You can fix this by registering Base* as a type that can be used to point to a BaseWrapper*:

class_<BaseWrapper, noncopyable, Base*>("Base")
        .def("func", pure_virtual(&Base::func));

But it seems that this means that Base can't have a pure virtual function...

Sign up to request clarification or add additional context in comments.

4 Comments

Yep, making Base::func() not pure solves the problem. Thanks, at least for this solution. But is there some workaround that does not change any existing API?
It isn't just making it not pure that solves the problem though, it is also registering Base* as a pointer type to BaseWrapper, unless I'm mistaken? Perhaps there is a way to coerce boost python into accepting a type with pure virtual methods as a pointer type...
Yes, I meant making func() not pure and registering Base* ptr solved the problem. Can you explain better how can I make python accept a type with pure virtuals?
Well it's boost python that rejects it. I think the place to start would be to look at the compiler error message that you get if you declare Base* as a pointer type for BaseWrapper, and leave the function as pure virtual.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.