![]() |
Default Arguments |
![]() |
![]() |
![]() |
Boost.Python wraps (member) function pointers. Unfortunately, C++ function pointers carry no default argument info. Take a function f with default arguments:
int f(int, double = 3.14, char const* = "hello");
But the type of a pointer to the function f has no information about its default arguments:
int(*g)(int,double,char const*) = f; // defaults lost!
When we pass this function pointer to the def function, there is no way to retrieve the default arguments:
def("f", f); // defaults lost!
Because of this, when wrapping C++ code, we had to resort to manual wrapping as outlined in the previous section, or writing thin wrappers:
// write "thin wrappers"
int f1(int x) { f(x); }
int f2(int x, double y) { f(x,y); }
/*...*/
// in module init
def("f", f); // all arguments
def("f", f2); // two arguments
def("f", f1); // one argument
When you want to wrap functions (or member functions) that either:
Boost.Python now has a way to make it easier. For instance, given a function:
int foo(int a, char b = 1, unsigned c = 2, double d = 3)
{
/*...*/
}
The macro invocation:
BOOST_PYTHON_FUNCTION_OVERLOADS(foo_overloads, foo, 1, 4)
will automatically create the thin wrappers for us. This macro will create a class foo_overloads that can be passed on to def(...). The third and fourth macro argument are the minimum arguments and maximum arguments, respectively. In our foo function the minimum number of arguments is 1 and the maximum number of arguments is 4. The def(...) function will automatically add all the foo variants for us:
.def("foo", foo, foo_overloads());
Objects here, objects there, objects here there everywhere. More frequently than anything else, we need to expose member functions of our classes to Python. Then again, we have the same inconveniences as before when default arguments or overloads with a common sequence of initial arguments come into play. Another macro is provided to make this a breeze.
Like BOOST_PYTHON_FUNCTION_OVERLOADS, BOOST_PYTHON_FUNCTION_OVERLOADS may be used to automatically create the thin wrappers for wrapping member functions. Let's have an example:
struct george
{
void
wack_em(int a, int b = 0, char c = 'x')
{
/*...*/
}
};
The macro invocation:
BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(george_overloads, wack_em, 1, 3)
will generate a set of thin wrappers for george's wack_em member function accepting a minimum of 1 and a maximum of 3 arguments (i.e. the third and fourth macro argument). The thin wrappers are all enclosed in a class named george_overloads that can then be used as an argument to def(...):
.def("wack_em", &george::wack_em, george_overloads());
See the overloads reference for details.
A similar facility is provided for class constructors, again, with default arguments or a sequence of overloads. Remember init<...>? For example, given a class X with a constructor:
struct X
{
X(int a, char b = 'D', std::string c = "constructor", double d = 0.0);
/*...*/
}
You can easily add this constructor to Boost.Python in one shot:
.def(init<int, optional<char, std::string, double> >())
Notice the use of init<...> and optional<...> to signify the default (optional arguments).
![]() |
![]() |
![]() |
Copyright © 2002-2003 David Abrahams
Copyright © 2002-2003 Joel de Guzman
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.