4

EDIT: Solved, my mistake; explained in my answer.

I have this:

std::vector < boost::shared_ptr < Entity > > entities;

and I try to expose it through SWIG like this:

%include "boost_shared_ptr.i"
%include "std_vector.i"

%shared_ptr(Entity)
%include <Entity.h>

namespace std {
    %template(EntityVector) vector<boost::shared_ptr<Entity> >;
};

%include <TheFileWithEntities.h>

However, in Python entities ends up being a tuple:

import MyModule
print type(MyModule.cvar.entities)
# Output: (type 'tuple')

I've Googled for this, but could not find any concrete examples on how to wrap this. One page gave a small example for wrapping it for C#, but it didn't help in my case.

Any help is greatly appreciated.

morrog
  • 664
  • 1
  • 8
  • 17

3 Answers3

5

I had some difficulty getting a Python sequence of pointer objects to automatically convert into a std::vector of pointer objects. I am currently (stuck) using Swig 1.3; YMMV if you're using Swig 2. The trick was to instantiate in the Swig interface file (with %template) not just the vector, and not just the object, but the pointer objects also:

%include "std_vector.i"
%template(myObjectT) namespace::of::myObject<T>;
%template(myObjectPtrT) boost::shared_ptr<namespace::of::myObject<T> >;
%template(myObjectVectorT) std::vector<boost::shared_ptr<namespace::of::myObject<T> > >;

Without the myObjectPtrT, Swig doesn't seem to know enough to convert a Python sequence of pointers to myObjectT to a myObjectVectorT.

UPDATE: For some reason I haven't yet been able to figure out, this leads to not being able to call methods on myObjectT from a myObjectPtrT, even though I've also used SWIG_SHARED_PTR(myObjectT, myObject<T>).

Paul Price
  • 2,657
  • 30
  • 26
0

See How to expose std::vector<int> as a Python list using SWIG? for probably good info

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Thanks for the response, but as you can see in my question, I already know how to wrap an std::vector. The issue is wrapping an std::vector of boost::shared_ptr's. SWIG seems to expose it as a tuple because it can't figure out the shared_ptr part of it. – morrog Apr 04 '11 at 21:32
  • Yes, thank you, I've read that, but I didn't see anything relevant. Again, I can wrap boost::shared_ptr and I can wrap std::vector, and those work as expected. The issue is specifically std::vector < boost::shared_ptr < Entity > >, which shows up in Python as a tuple. Python can access the tuple, view the things inside of it, manipulate the individual Entities inside the tuple, but it can't append or modify it ... because it's a tuple. – morrog Apr 05 '11 at 01:22
  • I figured out the issue and edited my question with the solution. Thank you for taking the time to help! – morrog Apr 05 '11 at 01:35
0

SWIG seems to wrap global variables of type std::vector into tuples. The solution is to move entities into a class, and access it through an instance of that class. Example:

class Globals
{
public:
     std::vector < boost::shared_ptr < Entity > > entities;
};

extern Globals globals;
morrog
  • 664
  • 1
  • 8
  • 17