[C++-sig] passing a vector of structs
Matthew Scouten
matthew.scouten at gmail.com
Wed Oct 17 22:53:31 CEST 2007
On 10/17/07, Matthew Scouten <matthew.scouten at gmail.com> wrote:
> On 10/16/07, Roman Yakovenko <roman.yakovenko at gmail.com> wrote:
> > On 10/16/07, Matthew Scouten <matthew.scouten at gmail.com> wrote:
> > > I have a vector of 'struct foo' in c++ that needs to be passed to a
> > > function python.
> > >
> > > 'struct foo' is an extremely simple structure containing 3 ints and a
> > > trivial ctor.
> > >
> > > so I create a foo_wrapper:
> > >
> > > struct foo_wrapper : foo , wrapper<foo>
> > > {
> > > foo_wrapper(const foo& f);
> > > foo_wrapper();
> > > };
> >
> > In this case you don't need to create wrapper
> >
> > > and export it:
> > >
> > > class_<foo_wrapper>("foo")
> > > .def(init<>())
> > > .def_readwrite("iE", &foo::iE )
> > > .def_readwrite("bA", &foo::bA)
> > > .def_readwrite("bL", &foo::bL)
> > > ;
> > >
> > > next I export a vector of foo_wrappers:
> > >
> > > class_< std::vector<foo_wrapper> >("VectorOfFoo")
> > > .def(vector_indexing_suite<
> > std::vector<foo_wrapper>, true >() );
> > >
> > > I pass the vector<foo> to a python function:
> > >
> > > Traceback (most recent call last):
> > > File "C:\redacted", line 23, in <module>
> > > pc.RequestExchangeList()
> > > TypeError: No to_python (by-value) converter found for C++ type: class
> > > std::vector<struct foo ,class std::allocator<struct foo > >
> > >
> > > I try to copy the elements to a new vector<foo_wrapper>, it seems to
> > > work fine, untill I try to access an element of that vector and get:
> > >
> > > Traceback (most recent call last):
> > > File "<stdin>", line 1, in <module>
> > > File "<stdin>", line 7, in OnExchangeList
> > > TypeError: No to_python (by-value) converter found for C++ type:
> > > struct TTExchangeStruct_wrapper
> > >
> > > So what am I doing wrong? How am I supposed to pass a vector of
> > > structs from c++ to python?
> >
> >
> > You need to post small and complete example.
> >
> > --
> > Roman Yakovenko
>
> Right, OK:
> TTExchangeStruct_wrapper is my foo_wrapper. I forgot to change that
> when sanitizing and simplifying me example. I split out the problem
> code and made a stand alone compilable example:
>
> c++ & boost::python:
>
> struct foo
> {
> foo():one(1),two(2),three(3) {}
>
> int one;
> int two;
> int three;
> };
>
> //The std::vector Indexing Suite seems to want this
> //I Don't know why.
> bool operator==(foo lhs ,foo rhs)
> {
> return &lhs == &rhs;
> }
>
> struct foo_wrapper : foo , wrapper<foo>
> {
> foo_wrapper(const foo& f);
> foo_wrapper();
> };
>
> foo_wrapper::foo_wrapper(const foo& exch): foo(exch), wrapper<foo>(){}
>
> foo_wrapper::foo_wrapper(): foo(), wrapper<foo>(){}
>
> class busyBox
> {
> public:
> int callout();
> virtual void callback(std::vector<foo> vf) {};
> };
>
> int busyBox::callout()
> {
> std::vector<foo> vf(10);
> callback(vf);
> return 0;
> }
>
> class busyBox_wrapper: public busyBox, public wrapper<busyBox>
> {
> public:
> busyBox_wrapper();
> busyBox_wrapper(const busyBox &);
> int callout();
> virtual void callback(std::vector<foo> vf);
> void default_callback(std::vector<foo> vf);
> };
>
> busyBox_wrapper::busyBox_wrapper() : busyBox(), wrapper<busyBox>(){}
>
> busyBox_wrapper::busyBox_wrapper(const busyBox &bb ) : busyBox(bb),
> wrapper<busyBox>(){}
>
> int busyBox_wrapper::callout()
> {
> return busyBox::callout();
> }
>
> void busyBox_wrapper::callback (std::vector<foo> vf)
> {
> if (override callbackPy = this->get_override("callback"))
> {
>
> std::vector<foo_wrapper> vfw;
> for (unsigned int i = 0; i < vf.size(); ++i)
> vfw.push_back(vf[i]);
>
> //callbackPy(vf);
> callbackPy(vfw);
>
> return;
> }
> return busyBox::callback(vf);
> }
>
> void busyBox_wrapper::default_callback(std::vector<foo> vf)
> {
> return busyBox::callback(vf);
> }
>
>
>
> BOOST_PYTHON_MODULE(BusyBox)
> {
>
> class_<busyBox_wrapper>("busyBox")
> .def("callback",&busyBox_wrapper::default_callback)
> .def("callout", &busyBox_wrapper::callout);
>
> class_<foo_wrapper>("foo")
> .def(init<>())
> .def_readwrite("one", &foo::one )
> .def_readwrite("two", &foo::two)
> .def_readwrite("three", &foo::three)
> ;
>
> class_< std::vector<foo_wrapper> >("std::vectorOfFoo")
> .def(vector_indexing_suite< std::vector<foo_wrapper>, true>());
> }
>
> and here is the python code to invoke the error:
>
> import BusyBox
>
> class subBusybox(BusyBox.busyBox):
> def callback(self, vf):
> print [x for x in vf]
>
>
> sbb = subBusybox()
> sbb.callout()
>
> and here it the error itself(it fails while invoking the 'print [x for
> x in vf]' line ):
>
> Traceback (most recent call last):
> File "<stdin>", line 1, in <module>
> File "<stdin>", line 3, in callback
> TypeError: No to_python (by-value) converter found for C++ type:
> struct foo_wrapper
>
>
>
> To reiterate my question: I need to pass a vector of structs from a
> c++ function to a python function. What am I doing wrong?
>
UPDATE: Well, with no reply from the list, I spent all day trying to
find my error. It turns out that I was temporarily stupid.
If the above lines are changed from:
class_< std::vector<foo_wrapper> >("std::vectorOfFoo")
.def(vector_indexing_suite< std::vector<foo_wrapper>, true>());
to:
class_< std::vector<foo> >("std::vectorOfFoo")
.def(vector_indexing_suite< std::vector<foo>, true>());
it fixes everything.
More information about the Cplusplus-sig
mailing list