Attachment 'py_boost_function.hpp'
Download
Toggle line numbers
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.