[C++-sig] A wrapped class contains another wrapped class. Hilarity ensues.

Matthew Scouten matthew.scouten at gmail.com
Tue Nov 27 18:59:48 CET 2007


AH! yes that worked. Thank you so much. It seems the real WTF here was that
it seemed to work fine when the foo was instantiated directly from python.
Because that seemed to work, I thought I was doing everything right until I
get further into wrapping my library.

Please ignore my earlier begging email. I was way the heck down the wrong
path, looking for the wrong solutions, and getting very frustrated.

Thank you all.

On Nov 27, 2007 1:50 AM, Roman Yakovenko <roman.yakovenko at gmail.com> wrote:

> On Nov 16, 2007 10:31 PM, Matthew Scouten <matthew.scouten at gmail.com>
> wrote:
> > I have 2 c++ classes called foo and bar. I wrapped both. bar contains a
> foo as a public data member. foo contains a function called get_buffer that
> is exported as "__str__" and as the getter of the property 'buffer'
> >
> > if I construct a foo, I can call that function with no problem.
> > if I create a bar and try to call the function on its foo I get an
> error.
> >
> > My C++ and B::P code:
> >
> > class foo
> > {
> > public:
> >
> >     foo() {std::strcpy(buffer, "good bye cruel world!\0\0");}
> >     char buffer[24];
> > };
> >
> > struct foo_wrapper : foo , wrapper<foo>
> > {
> >         foo_wrapper(const foo& f);
> >         foo_wrapper();
> >
> >         //property getters
> >         std::string get_buffer() const;
> > };
> >
> > foo_wrapper::foo_wrapper(const foo& exch): foo(exch), wrapper<foo>(){}
> >
> > foo_wrapper::foo_wrapper(): foo(), wrapper<foo>(){}
> >
> > std::string foo_wrapper::get_buffer() const
> > {
> >     return std::string(foo::buffer);
> > }
> >
> >
> > class bar
> > {
> > public:
> >     foo f;
> > };
> >
> > class bar_wrapper: public bar, public wrapper<bar>
> > {
> > public:
> >     bar_wrapper();
> >     bar_wrapper(const bar &);
> > };
> >
> > bar_wrapper::bar_wrapper() : bar(), wrapper<bar>(){}
> >
> > bar_wrapper::bar_wrapper(const bar &bb ) : bar(bb), wrapper<bar>(){}
> >
> > BOOST_PYTHON_MODULE(BusyBox)
> > {
> >
> >     class_<foo_wrapper>("foo")
> >         .def(init<>())
> >         .add_property("buffer", &foo_wrapper::get_buffer)
> >         .def("__str__", &foo_wrapper::get_buffer)
> >         ;
> >
> >     class_<bar_wrapper>("bar")
> >         .def_readwrite("f", &bar::f)
> >         ;
> > }
> >
> > A REPL session that demos the errors:>>> from BusyBox import *
> > >>> f1 = foo()
> > >>>
> > >>> f1.buffer
> > 'good bye cruel world!'
> > >>> str(f1)
> > 'good bye cruel world!'
> > >>>
> > >>> b1 = bar()
> > >>>
> > >>> b1.f.buffer #Generates error
> > Traceback (most recent call last):
> >   File "<stdin>", line 1, in <module>
> > Boost.Python.ArgumentError: Python argument types in
> >     None.None(foo)
> > did not match C++ signature:
> >     None(struct foo_wrapper {lvalue})
> > >>> str(b1.f)   #Generates error
> > Traceback (most recent call last):
> >   File "<stdin>", line 1, in <module>
> > Boost.Python.ArgumentError: Python argument types in
> >     foo.__str__(foo)
> > did not match C++ signature:
> >     __str__(struct foo_wrapper {lvalue})
> > >>>
> > >>> f2 = b1.f
> > >>>
> > >>> b2.buffer   #Generates error
> > Traceback (most recent call last):
> >   File "<stdin>", line 1, in <module>
> > NameError: name 'b2' is not defined
> > >>> str(f2)     #Generates error
> > Traceback (most recent call last):
> >   File "<stdin>", line 1, in <module>
> > Boost.Python.ArgumentError: Python argument types in
> >     foo.__str__(foo)
> > did not match C++ signature:
> >     __str__(struct foo_wrapper {lvalue})
> > >>>
> >
> > I feel like I must be doing something stupid. What is wrong?
>
> You don't have, while the error messages contains enough information
> it is really difficult to new user to understand what is going wrong.
>
>
> > >>> str(f2)     #Generates error
> > Traceback (most recent call last):
> >   File "<stdin>", line 1, in <module>
> > Boost.Python.ArgumentError: Python argument types in
> >     foo.__str__(foo)
> > did not match C++ signature:
> >     __str__(struct foo_wrapper {lvalue})
> > >>>
>
> The error message says that you cannot call foo.__str__ method with
> "foo" as "this" pointer, but you should provide "foo_wrapper" for this
> purpose. The library is right:
>
> >struct foo_wrapper : foo , wrapper<foo>
> > {
> >        ...
> >         std::string get_buffer() const;
> > };
>
> In order to call get_buffer, the object type should be "foo_wrapper",
> not "foo". You didn't exposed "foo_wrapper" class, but "foo".
> If you define get_buffer as
>
>
> struct foo_wrapper : foo , wrapper<foo>
>  {
>        ...
>         static std::string get_buffer(const foo& x ){ return
> std::string(x.buffer); }
>  };
>
> Everything will work as expected.
>
> The really confusing thing is that the library allowed you to call
> __str__ method on object constructed from Python. This is because
> internally it keeps foo_wrapper instance instead of "foo" one.
>
> HTH
>
> --
> Roman Yakovenko
> C++ Python language binding
> http://www.language-binding.net/
> _______________________________________________
> C++-sig mailing list
> C++-sig at python.org
> http://mail.python.org/mailman/listinfo/c++-sig
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20071127/dd8f593c/attachment.htm>


More information about the Cplusplus-sig mailing list