To expose overloaded functions in Python, simply def()
each
one with the same Python name:
inline int f1() { return 3; } inline int f2(int x) { return x + 1; } class X { public: X() : m_value(0) {} X(int n) : m_value(n) {} int value() const { return m_value; } void value(int v) { m_value = v; } private: int m_value; }; ... BOOST_PYTHON_MODULE_INIT(overload_demo) { try { boost::python::module_builder overload_demo("overload_demo"); // Overloaded functions at module scope overload_demo.def(f1, "f"); overload_demo.def(f2, "f"); boost::python::class_builder<X> x_class(overload_demo, "X"); // Overloaded constructors x_class.def(boost::python::constructor<>()); x_class.def(boost::python::constructor<int>()); // Overloaded member functions x_class.def((int (X::*)() const)&X::value, "value"); x_class.def((void (X::*)(int))&X::value, "value"); ...
Now in Python:
>>> from overload_demo import * >>> x0 = X() >>> x1 = X(1) >>> x0.value() 0 >>> x1.value() 1 >>> x0.value(3) >>> x0.value() 3 >>> X('hello') TypeError: No overloaded functions match (X, string). Candidates are: void (*)() void (*)(int) >>> f() 3 >>> f(4) 5
Notice that overloading in the Python module was produced three ways:
int f1()
and int f2(int)
and exposing them as f
in Python.
class X
X::value
.
Techniques 1. and 3. above are really alternatives. In case 3, you need to form a pointer to each of the overloaded functions. The casting syntax shown above is one way to do that in C++. Case 1 does not require complicated-looking casts, but may not be viable if you can't change your C++ interface. N.B. There's really nothing unsafe about casting an overloaded (member) function address this way: the compiler won't let you write it at all unless you get it right.
This approach is not neccessarily better, but may be preferable for some people who have trouble writing out the types of (member) function pointers or simply prefer to avoid all casts as a matter of principle:
// Forwarding functions for X::value inline void set_x_value(X& self, int v) { self.value(v); } inline int get_x_value(X& self) { return self.value(); } ... // Overloaded member functions x_class.def(set_x_value, "value"); x_class.def(get_x_value, "value");
Here we are taking advantage of the ability to expose C++ functions at namespace scope as Python member functions.
The function overload resolution mechanism works as follows:
def()
ed. The first function whose signature can be made to
match each argument passed is the one which is ultimately called.
This means in particular that you cannot overload the same function on
both ``int
'' and ``float
'' because Python
automatically converts either of the two types into the other one.
If the ``float
'' overload is found first, it is used
also used for arguments of type ``int
'' as well, and the
``int
'' version of the function is never invoked.
Next: Inheritance Previous: Overridable Virtual Functions Up: Top
© Copyright David Abrahams 2001. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This document is provided ``as is'' without express or implied warranty, and with no claim as to its suitability for any purpose.
Updated: Mar 6, 2001