[C++-sig] Exposing boost::function
François Duranleau
duranlef at iro.umontreal.ca
Mon May 15 19:57:44 CEST 2006
Hi all!
Last weekend, I though of a few things about exposing boost::function to
Python and I would like to share those ideas and know what others think
about it. This is also a kind of follow up to the thread
http://thread.gmane.org/gmane.comp.python.c++/9062/focus=9101 .
Simply put, the problem is exposing something like:
template < Func >
void do_something( Func f ) { ... }
where Func is a function of some kind (conceptually).
The first step of the solution would be to actually expose this:
using namespace boost::python ;
typedef boost::function< the_appropriate_signature > function_type ;
def( "do_something" , & do_something< function_type > ) ;
but then (actually, before) when have to expose function_type. Suppose we
do this:
class_< function_type >( "Function" )
.def( "__call__" , & function_type::operator() )
;
and suppose we did something to create a Function from any callable
object, then in Python, we would have to call do_something like, e.g.:
do_something( Function( callable_object ) )
In C++, there is an implicit conversion between functors and functions to
boost::function, so it would be very nice to do the same in Python, e.g.:
do_something( callable_object )
Up to here we can ask ourselves: then is there any need to really expose
boost::function?
This is where I worked a few things. At first I thought: well, no, since
in Python there is no need for such a class (it has its own mechanisms to
abstract callbacks), then boost::function should be completely
transparent. That means when we return a boost::function in C++, we should
extract its content to Python.
To avoid a very long message, I won't post the code here. You can find it
there:
http://www-etud.iro.umontreal.ca/~duranlef/python/function.hpp
http://www-etud.iro.umontreal.ca/~duranlef/python/function_test.cpp
http://www-etud.iro.umontreal.ca/~duranlef/python/function_test.py
Read the comments.
It is to note that as much as we can, we could like to avoid calling back
to Python when calling the operator() of a boost::function in C++ if it
contains a C++ object exposed to Python. We can achieve this to a limited
extend with boost::python::implicitly_convertible<>, as presented in the
code above.
Now, there is a problem when a C++ function returns a boost::function,
because its content might not be something exposed to Python, and as you
can see in the code above (in function.hpp, the to_python converter),
things can get ugly. This morning, I thought of another, simpler approach:
expose boost::function "regularly", plus add some extra implicit
converters to allow the above. This avoid the return problem, but we have
an extra level of indirection when calling the "function" in Python.
The code for that version is here:
http://www-etud.iro.umontreal.ca/~duranlef/python/function_v2.hpp
http://www-etud.iro.umontreal.ca/~duranlef/python/function_test_v2.cpp
http://www-etud.iro.umontreal.ca/~duranlef/python/function_test_v2.py
There is a Jamfile (and Jamrules, both inspired by the Boost.Python
tutorial) here to compile both version:
http://www-etud.iro.umontreal.ca/~duranlef/python/Jamfile
http://www-etud.iro.umontreal.ca/~duranlef/python/Jamrules
P.S.: the code is not complete and the way things are written is not
necessarily the best way. It is mostly just a proof of concept.
--
François Duranleau
LIGUM, Université de Montréal
"Like individual, like organization. Overspecialization leads to death."
- Motoko Kusanagi, in _Ghost in the Shell_
More information about the Cplusplus-sig
mailing list