Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

boost.python confused about similar constructor

Tags:

c++

python

boost

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?

like image 691
leon Avatar asked Nov 15 '11 17:11

leon


1 Answers

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.

like image 98
alex vasi Avatar answered Sep 22 '22 13:09

alex vasi