[C++-sig] Re: How to expose virtual function with default arguments in boost.python ?
David Abrahams
dave at boost-consulting.com
Sun Dec 5 00:18:15 CET 2004
Baptiste Lepilleur wrote:
> I'm basically trying to expose the virtual member function
> 'set' of the following code:
>
> ----
> class VirtualNonCopyable {
> public:
> virtual void set( const std::string &name_, int size_ = 10, int
width_ =
> 12 ) {
> name = name_;
> size = size_;
> width = width_;
> }
>
> std::string name;
> int size;
> int width;
> };
>
> inline VirtualNonCopyable &getVirtualNonCopyable() {
> static VirtualNonCopyable instance;
> return instance;
> }
> ----
>
> Pyste generate the following binding code (full source attached):
>
> ----
> class_< VirtualNonCopyable, py::VirtualNonCopyable_Wrapper
>
>>("VirtualNonCopyable", init< >())
>
> .def("set", &VirtualNonCopyable::set,
> &py::VirtualNonCopyable_Wrapper::default_set_3)
> .def("set", &py::VirtualNonCopyable_Wrapper::default_set_1)
> .def("set", &py::VirtualNonCopyable_Wrapper::default_set_2)
<snip>
> ----
> Pyste is still using old-style polymorphism. default_set_1,
default_set_2
> and default_set_3 are methods forwarding to the base class
implementation.
> The binding for default_set_1 should be the one triggered by the
python code
> below.
>
> The bug is demonstrated by the following python code:
>
> object = getVirtualNonCopyable() # Get a instance of
VirtualNonCopyable
> from C++
> object.set( 'abc' ) # use overloading resolution to
apply the default values
Right. The problem here is that all the overloads for handling
default arguments take a first argument of
py::VirtualNonCopyable_Wrapper {lvalue}
(because they are member functions of VirtualNonCopyable_Wrapper)
but the object you're creating in C++ is only of type
VirtualNonCopyable {lvalue}
You can see most of this in the overload set described in the error
message below, if you look carefully (using an initial type
other than std::string would make it clearer).
So one way to make it work is to add some functions that can be
called for VirtualNonCopyable objects:
void set_2(VirtualNonCopyable& self, std::string s, int p1)
{ self.set(s,p1); }
void set_1(VirtualNonCopyable&& self, std::string s)
{ self.set(s); }
And before any of the other defs (so if the object is actually a
VirtualNonCopyable_Wrapper the other overloads will take
priority), but in any order, you do:
.def("set", set_1)
.def("set", set_2)
Alternatively, you should be able to avoid defining any helper
functions this way:
.def(
"set"
, make_function(
&VirtualNonCopyable::set
, mpl::vector<void,std::string,int,int>())
)
.def(
"set"
, make_function(
&VirtualNonCopyable::set
, mpl::vector<void,std::string,int>())
)
Incidentally, all this applies just as well even after you fix
Pyste to use new-style polymorphism.
HTH,
--
Dave Abrahams
Boost Consulting
http://www.boost-consulting.com
More information about the Cplusplus-sig
mailing list