Reputation: 5091
I have a class that looks like
class Foo{
Foo();
Foo(int i);
Foo(bool b);
Foo(double d);
};
and I expose my class to python as usual
class_<Foo>("Foo")
.def(init<int>())
.def(init<bool>())
.def(init<double>());
when I try to use to in python, the python code always cast the c'tor parameter into double (which is always the last one in the class def export). Is there a way to explicit tell boost.python how to explicitly handle by the type?
Upvotes: 7
Views: 3384
Reputation: 5344
Well, you can change the order of constructor's definitions, the last one will have higher priority. Here is my results:
class_<Foo>("Foo")
.def(init<bool>())
.def(init<double>())
.def(init<int>());
Foo() # calls Foo()
Foo(True) # calls Foo(int)
Foo(1) # calls Foo(int)
Foo(4.2) # calls Foo(double)
As you see, it's not a perfect solution. So, if you really need to make overloaded constructors work I suggest to roll your own factory function.
using namespace boost::python;
static boost::shared_ptr<Foo>
makeFoo(const object& data)
{
boost::shared_ptr<Foo> obj;
if (PyBool_Check(data.ptr())) {
bool val = extract<bool>(data);
obj.reset(new Foo(val));
}
else if (PyFloat_Check(data.ptr())) {
double val = extract<double>(data);
obj.reset(new Foo(val));
}
else {
int val = extract<int>(data);
obj.reset(new Foo(val));
}
return obj;
}
class_<Foo>("Foo")
.def("__init__", make_constructor(makeFoo));
And using makeFoo:
Foo() # calls Foo()
Foo(True) # calls Foo(bool)
Foo(1) # calls Foo(int)
Foo(4.2) # calls Foo(double)
By the way, docs at python.org can be somewhat helpful.
Upvotes: 13