3

From my research it seems not very trivial to wrap std::vector that holds pointer types. For example:

std::vector<GameObject*>

I've looked at boost python vector_index_suite but it just gives me the runtime error:

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

I have already exposed GameObject:

class_<GameObject>("GameObject") ...

So it have come to my understanding it's not possible with an out of the box solution. I have to do some kind of wrapper? Could someone just help me out where I should start?

3 Answers 3

2

The way to fix this is to explicitly state that your class wrapper applies to the pointer type as well.

class_<GameObject, GameObject*>("GameObject") ...

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

Comments

1

Can't comment @jkp but his hint did the trick for me. My minimalistic case:

RenderWorld.h

class RenderWorld {
    public:
        ...
        void addEntity(RenderEntity* entity) {entities.push_back(entity);};
        std::vector<RenderEntity*> getEntities(void) {return entities;};
    private:
        std::vector<RenderEntity*> entities;
 };

RenderEntity.h

 class RenderEntity {
     public:
         int getID(void) {return 42;};
 };

python-exportage.py.h (compiles to exported.pyd)

BOOST_PYTHON_MODULE(exported)
{
    class_<RenderWorld>("RenderWorld")
        .def("addEntity", &RenderWorld::addEntity)
        .def("getEntities", &RenderWorld::getEntities)
    ;

    class_<RenderEntity, RenderEntity*>("RenderEntity")
        .def("getID", &RenderEntity::getID)
    ;

    class_<std::vector<RenderEntity*> >("PyVec")
         .def(boost::python::vector_indexing_suite<std::vector<RenderEntity*> >())
    ;
}

my python session:

>>> import exported
>>> world = exported.RenderWorld()
>>> world
<exported.RenderWorld object at 0x00000000024A0E58>
>>> e1 = exported.RenderEntity()
>>> e1
<exported.RenderEntity object at 0x000000000284DF48>
>>> e1.getID()
42
>>> world.addEntity(e1)
>>> world.getEntities()
<exported.PyVec object at 0x000000000234B1B0>  
>>> world.getEntities()[0]
<exported.RenderEntity object at 0x0000000002441F50>
>>> world.getEntities()[0].getID()
42
>>> e1 == world.getEntities()[0]
False

Notable: The RenderEntity* will be wrapped in an other object. Look at these addresses and the last check. It's logical in a c++ perspective, but not in the python domain.

Comments

0

You have to also wrap your GameObject class. It won't work until you have a Python wrapper for the member object. If you don't want to expose members of the class, you can omit them, and just have an opaque object.

Also, boost::python works really well with shared pointers. This gives you an added benefit of safe memory handling. Any chance you can change std::vector<GameObject*> to std::vector<boost::shared_ptr<GameObject> >? This will work much better.

1 Comment

Thanks for the answer, Yes, I have already exposed the GameObject with boost.python. It still doesn't work with vector<GameObject*>. I can't implement shared_ptr right now. Do you have an other suggestion how I can export the vector class?

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.