Attachment 'py_boost_function.hpp'

Download

   1 /******************************************************************************
   2  * How to wrap boost.function objects with boost.python and use them both from
   3  * C++ and Python.
   4  * 
   5  *   AUTHOR: Alcides Viamontes Esquivel
   6  *
   7  *   LICENSE: You're free to use this file for whatever you want. You're 
   8  *            specially welcome to improve it in any way and give the 
   9  *            changes back.
  10  *
  11  ******************************************************************************
  12  *
  13  * Usage example:
  14  *
  15  *     For the boost.python C++ module:
  16  *     
  17  *     ...
  18  *     #include <boost/python.hpp>
  19  *     ...
  20  *     #include "py_boost_function.hpp"
  21  *     ...
  22  *
  23  *     void module_greeter_f(std::string const& origin)
  24  *     {
  25  *           cout << "Hello world, by " << origin << endl;
  26  *     }
  27  *
  28  *
  29  *     boost::function< void( std::string const& ) > module_greeter( 
  30  *          module_greeter_f
  31  *     ) ;
  32  *     ...
  33  *
  34  *     BOOST_PYTHON_MODULE( foo ) {
  35  *
  36  *          using namespace boost.python;
  37  *          ...
  38  *
  39  *          def_function< void(string const&) >(
  40  *              "greeter_function_t", 
  41  *              "A greeting function" 
  42  *          );
  43  *
  44  *          ...
  45  *          scope().attr("module_greeter") = module_greeter;
  46  *     }
  47  *
  48  * From python code:
  49  *
  50  *     - Invoke:
  51  *
  52  *          >>> import foo
  53  *          >>> foo.module_greeter("world")
  54  *
  55  *     - Create instances from python:
  56  *             
  57  *          >>> def my_greetings(hi):
  58  *          >>> ... print hi, ", world"
  59  *          >>> ...
  60  *          >>> grfunc = foo.greeter_function_t.from_callable( my_greetings )
  61  *
  62  */
  63 
  64 
  65 
  66 #ifndef YOUR_INCLUDE_GUARD
  67 #define YOUR_INCLUDE_GUARD 
  68 
  69 #include <boost/python.hpp>
  70 
  71 #include <boost/function.hpp>
  72 #include <boost/function_types/function_type.hpp>
  73 #include <boost/function_types/result_type.hpp>
  74 #include <boost/function_types/is_function.hpp>
  75 
  76 #include <boost/type_traits/function_traits.hpp>
  77 
  78 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
  79 #include <boost/preprocessor/repetition/enum_params.hpp>
  80 #include <boost/preprocessor/repetition/repeat.hpp>
  81 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
  82 
  83 
  84 namespace detail{
  85 
  86     template <typename RT, int arity>
  87     struct pyobject_invoker;
  88 
  89     template <typename RT> 
  90     struct pyobject_invoker<RT, 0 > 
  91     { 
  92         boost::python::object callable; 
  93         
  94         RT operator( )( )
  95         {
  96             return boost::python::extract<RT>( callable( ) );
  97         }
  98     };
  99 
 100 #define MAKE_PYOBJECT_INVOKER(z, n, data) \
 101     template <typename RT> \
 102     struct pyobject_invoker<RT, n > \
 103     { \
 104         boost::python::object callable; \
 105         \
 106         template < BOOST_PP_ENUM_PARAMS(n, typename Arg) > \
 107         RT operator( )(BOOST_PP_ENUM_BINARY_PARAMS(n, Arg, arg ) )\
 108         {\
 109             boost::python::object o = callable( BOOST_PP_ENUM_PARAMS(n, arg) );\
 110             return boost::python::extract<RT>( o );\
 111         }\
 112     };
 113     
 114 BOOST_PP_REPEAT_FROM_TO( 1, 6, MAKE_PYOBJECT_INVOKER, nothing );
 115 
 116 #undef MAKE_PYOBJECT_INVOKER
 117     
 118     template <typename FT>
 119     boost::function< FT > function_frompyobj( boost::python::object o )
 120     {
 121         const int arity = boost::function_traits< FT >::arity;
 122         typedef 
 123             typename  boost::function_types::result_type< FT >::type
 124             result_type;
 125         pyobject_invoker<result_type, arity > inv;
 126         inv.callable = o;
 127         return inv;
 128     }
 129 
 130 } // namespace detail
 131 
 132 template <typename FT>
 133 void def_function(const char* func_name, const char* func_doc)
 134 {
 135     BOOST_STATIC_ASSERT( boost::function_types::is_function< FT >::value ) ;
 136     namespace bp = boost::python;
 137     typedef boost::function<FT> function_t;
 138     bp::class_< function_t >
 139     (func_name, func_doc, bp::no_init)
 140         .def("__call__", &function_t::operator() )
 141         .def("from_callable", &detail::function_frompyobj<FT> )
 142         .staticmethod("from_callable")
 143     ;
 144 } // def_function0
 145 
 146 
 147 
 148 
 149 #endif // YOUR_INCLUDE_GUARD
 150 

Attached Files

To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.

You are not allowed to attach a file to this page.

Unable to edit the page? See the FrontPage for instructions.