[C++-sig] [python] Function objects in place of member functions

troy d. straszheim troy at resophonic.com
Mon Oct 12 01:44:29 CEST 2009


Ravi wrote:
[snip]
> 
> In order to use a function object in place of a free function, one must 
> specialize/overload
>   boost::python::detail::get_signature
> which, for some reason, does not account for function objects. Here's a very 
> simple example that works:
> 
[snip]
> 
> However, note that the overload of get_signature precedes the inclusion of the 
> boost.python headers, which is extremely inconvenient. However, if the headers 
> are moved to their proper location as in the following,
> 
[snip]
> 
> Why is the overloaded get_signature not picked up when it is declared *after* 
> the inclusion of the headers?
> 

I'm not sure why it isn't picked up.  I've been working in this area, 
replacing most of detail/caller.hpp and detail/invoke.hpp with 
boost.fusion, seen here:

http://gitorious.org/~straszheim/boost/straszheim/blobs/python/boost/python/detail/caller.hpp

In the process, I overhauled get_signature to use boost::function_types, 
and to be a metafunction, not a function:

http://gitorious.org/~straszheim/boost/straszheim/blobs/python/boost/python/signature.hpp

The overall effect is a lot less preprocessor stuff to look around.

I have function objects (given a specialization of get_signature), and 
boost::function (only up to 3 arguments ATM) working,
here's the test (which passes):

/////////////////////////////////////

#include <boost/mpl/vector.hpp>
#include <boost/function.hpp>
#include <boost/python/class.hpp>
#include <boost/python/module.hpp>

namespace mpl = boost::mpl;

struct X { int y; };

struct FnObject
{
   typedef int result_type;

   int operator()(X *x, int z) const
   {
     return z + x->y;
   }
};

int f1(X* x) { return x->y ; }
int f2(X* x, int i) { return x->y * i; }
int f3(X* x, int i, int j) { return x->y * i + j; }

namespace boost {
   namespace python {
     namespace detail {

       template<>
       struct get_signature<FnObject, X>
       {
	typedef mpl::vector<int, X*, int> type;
       };

     }
   }
}

using namespace boost::python;

BOOST_PYTHON_MODULE( function_objects_ext )
{
   FnObject fobj;
   boost::function<int(X*, int)> bf0(fobj);

   boost::function<int(X*)> bf1(f1);
   boost::function<int(X*, int)> bf2(f2);
   boost::function<int(X*, int, double)> bf3(f3);

   boost::python::class_<X>( "X" )
     .def( "fobj", fobj)
     .def( "bf0",  bf0)
     .def( "bf1",  bf1)
     .def( "bf2",  bf2)
     .def( "bf3",  bf3)
     .def_readwrite( "y", &X::y )
     ;
}

/////////////////////////////

 >>> from function_objects_ext import *
 >>> x = X()
 >>> x.y = 13
 >>> x.fobj(12)
25
 >>> x.bf1()
13
 >>> x.bf2(2)
26
 >>> x.bf3(2, -27)
-1

/////////////////////////////

I'm fairly new to the internals of boost.python, and only just now got 
this working...  Do you see problems with this, specifically the 
conversion of get_signature from function to metafunction?

-t




More information about the Cplusplus-sig mailing list