]>
Commit | Line | Data |
---|---|---|
1 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
2 | The Boost Parameter Library Python Binding Documentation | |
3 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
4 | ||
5 | :Authors: David Abrahams, Daniel Wallin | |
6 | :Contact: dave@boost-consulting.com, daniel@boostpro.com | |
7 | :organization: `BoostPro Computing`_ | |
8 | :date: $Date$ | |
9 | ||
10 | :copyright: Copyright David Abrahams, Daniel Wallin | |
11 | 2005-2009. Distributed under the Boost Software License, | |
12 | Version 1.0. (See accompanying file LICENSE_1_0.txt | |
13 | or copy at http://www.boost.org/LICENSE_1_0.txt) | |
14 | ||
15 | :abstract: Makes it possible to bind Boost.Parameter-enabled | |
16 | functions, operators and constructors to Python. | |
17 | ||
18 | |(logo)|__ | |
19 | ||
20 | .. |(logo)| image:: ../../../../boost.png | |
21 | :alt: Boost | |
22 | ||
23 | __ ../../../../index.htm | |
24 | ||
25 | .. _`BoostPro Computing`: http://www.boostpro.com | |
26 | ||
27 | ||
28 | .. role:: class | |
29 | :class: class | |
30 | ||
31 | .. role:: concept | |
32 | :class: concept | |
33 | ||
34 | .. role:: function | |
35 | :class: function | |
36 | ||
37 | .. |ParameterSpec| replace:: :concept:`ParameterSpec` | |
38 | ||
39 | .. contents:: | |
40 | :depth: 1 | |
41 | ||
42 | Introduction | |
43 | ------------ | |
44 | ||
45 | ``boost/parameter/python.hpp`` introduces a group of |def_visitors|_ that can | |
46 | be used to easily expose Boost.Parameter-enabled member functions to Python with | |
47 | Boost.Python. It also provides a function template ``def()`` that can be used | |
48 | to expose Boost.Parameter-enabled free functions. | |
49 | ||
50 | .. |def_visitor| replace:: ``def_visitor`` | |
51 | .. |def_visitors| replace:: ``def_visitors`` | |
52 | ||
53 | .. _def_visitor: def_visitors_ | |
54 | .. _def_visitors: ../../../python/doc/v2/def_visitor.html | |
55 | ||
56 | When binding a Boost.Parameter enabled function, the keyword tags | |
57 | must be specified. Additionally, because Boost.Parameter enabled | |
58 | functions are templates, the desired function signature must be | |
59 | specified. | |
60 | ||
61 | .. The keyword tags are specified as an `MPL Sequence`_, using the | |
62 | pointer qualifications described in |ParameterSpec|_ below. The | |
63 | signature is also specifid as an `MPL sequence`_ of parameter | |
64 | types. Additionally, ``boost::parameter::python::function`` and | |
65 | ``boost::parameter::python::def`` requires a class with forwarding | |
66 | overloads. We will take a closer look at how this is done in the | |
67 | tutorial section below. | |
68 | ||
69 | The keyword tags and associated argument types are specified as an `MPL | |
70 | Sequence`_, using the function type syntax described in |ParameterSpec|_ | |
71 | below. Additionally, ``boost::parameter::python::function`` and | |
72 | ``boost::parameter::python::def`` requires a class with forwarding overloads. | |
73 | We will take a closer look at how this is done in the tutorial section below. | |
74 | ||
75 | .. The last two sentences are terribly vague. Which namespace is | |
76 | .. ``function`` in? Isn't the return type always needed? What | |
77 | .. else are we going to do other than pass these sequences to | |
78 | .. function? | |
79 | ||
80 | .. _`MPL Sequence`: ../../../mpl/doc/refmanual/sequences.html | |
81 | .. _parameterspec: `concept ParameterSpec`_ | |
82 | ||
83 | Tutorial | |
84 | -------- | |
85 | ||
86 | In this section we will outline the steps needed to bind a simple | |
87 | Boost.Parameter-enabled member function to Python. Knowledge of the | |
88 | Boost.Parameter macros_ are required to understand this section. | |
89 | ||
90 | .. _macros: index.html | |
91 | ||
92 | The class and member function we are interested in binding looks | |
93 | like this: | |
94 | ||
95 | .. parsed-literal:: | |
96 | ||
97 | #include <boost/parameter/keyword.hpp> | |
98 | #include <boost/parameter/preprocessor.hpp> | |
99 | #include <boost/parameter/python.hpp> | |
100 | #include <boost/python.hpp> | |
101 | ||
102 | // First the keywords | |
103 | BOOST_PARAMETER_KEYWORD(tag, title) | |
104 | BOOST_PARAMETER_KEYWORD(tag, width) | |
105 | BOOST_PARAMETER_KEYWORD(tag, height) | |
106 | ||
107 | class window | |
108 | { | |
109 | public: | |
110 | BOOST_PARAMETER_MEMBER_FUNCTION( | |
111 | (void), open, tag, | |
112 | (required (title, (std::string))) | |
113 | (optional (width, (unsigned), 400) | |
114 | (height, (unsigned), 400)) | |
115 | ) | |
116 | { | |
117 | *… function implementation …* | |
118 | } | |
119 | }; | |
120 | ||
121 | .. @example.prepend('#include <cassert>') | |
122 | .. @example.replace_emphasis(''' | |
123 | assert(title == "foo"); | |
124 | assert(height == 20); | |
125 | assert(width == 400); | |
126 | ''') | |
127 | ||
128 | It defines a set of overloaded member functions called ``open`` with one | |
129 | required parameter and two optional ones. To bind this member function to | |
130 | Python we use the binding utility ``boost::parameter::python::function``. | |
131 | ``boost::parameter::python::function`` is a |def_visitor|_ that we'll instantiate | |
132 | and pass to ``boost::python::class_::def()``. | |
133 | ||
134 | To use ``boost::parameter::python::function`` we first need to define | |
135 | a class with forwarding overloads. This is needed because ``window::open()`` | |
136 | is a function template, so we can't refer to it in any other way. | |
137 | ||
138 | :: | |
139 | ||
140 | struct open_fwd | |
141 | { | |
142 | template <class A0, class A1, class A2> | |
143 | void operator()( | |
144 | boost::type<void>, window& self | |
145 | , A0 const& a0, A1 const& a1, A2 const& a2 | |
146 | ) | |
147 | { | |
148 | self.open(a0, a1, a2); | |
149 | } | |
150 | }; | |
151 | ||
152 | The first parameter, ``boost::type<void>``, tells the forwarding overload | |
153 | what the return type should be. In this case we know that it's always void | |
154 | but in some cases, when we are exporting several specializations of a | |
155 | Boost.Parameter-enabled template, we need to use that parameter to | |
156 | deduce the return type. | |
157 | ||
158 | ``window::open()`` takes a total of 3 parameters, so the forwarding function | |
159 | needs to take three parameters as well. | |
160 | ||
161 | .. Note:: | |
162 | ||
163 | We only need one overload in the forwarding class, despite the | |
164 | fact that there are two optional parameters. There are special | |
165 | circumstances when several overload are needed; see | |
166 | `special keywords`_. | |
167 | ||
168 | Next we'll define the module and export the class: | |
169 | ||
170 | :: | |
171 | ||
172 | BOOST_PYTHON_MODULE(my_module) | |
173 | { | |
174 | using namespace boost::python; | |
175 | namespace py = boost::parameter::python; | |
176 | namespace mpl = boost::mpl; | |
177 | ||
178 | class_<window>("window") | |
179 | .def( | |
180 | "open", py::function< | |
181 | open_fwd | |
182 | , mpl::vector< | |
183 | void | |
184 | , tag::title(std::string) | |
185 | , tag::width*(unsigned) | |
186 | , tag::height*(unsigned) | |
187 | > | |
188 | >() | |
189 | ); | |
190 | } | |
191 | ||
192 | .. @jam_prefix.append('import python ;') | |
193 | .. @jam_prefix.append('stage . : my_module /boost/python//boost_python ;') | |
194 | .. @my_module = build( | |
195 | output = 'my_module' | |
196 | , target_rule = 'python-extension' | |
197 | , input = '/boost/python//boost_python' | |
198 | , howmany = 'all' | |
199 | ) | |
200 | ||
201 | .. @del jam_prefix[:] | |
202 | ||
203 | ``py::function`` is passed two parameters. The first one is the class with | |
204 | forwarding overloads that we defined earlier. The second one is an `MPL | |
205 | Sequence`_ with the keyword tag types and argument types for the function | |
206 | specified as function types. The pointer syntax used in ``tag::width*`` and | |
207 | ``tag::height*`` means that the parameter is optional. The first element of | |
208 | the `MPL Sequence`_ is the return type of the function, in this case ``void``, | |
209 | which is passed as the first argument to ``operator()`` in the forwarding | |
210 | class. | |
211 | ||
212 | .. The | |
213 | pointer syntax means that the parameter is optional, so in this case | |
214 | ``width`` and ``height`` are optional parameters. The third parameter | |
215 | is an `MPL Sequence`_ with the desired function signature. The return type comes first, and | |
216 | then the parameter types: | |
217 | ||
218 | .. parsed-literal:: | |
219 | ||
220 | mpl::vector<void, std::string, unsigned, unsigned> | |
221 | *return type* *title* *width* *height* | |
222 | ||
223 | .. @ignore() | |
224 | ||
225 | That's it! This class can now be used in Python with the expected syntax:: | |
226 | ||
227 | >>> w = my_module.window() | |
228 | >>> w.open(title = "foo", height = 20) | |
229 | ||
230 | .. @example.prepend('import my_module') | |
231 | .. @run_python(module_path = my_module) | |
232 | ||
233 | .. Sorry to say this at such a late date, but this syntax really | |
234 | .. strikes me as cumbersome. Couldn't we do something like: | |
235 | ||
236 | class_<window>("window") | |
237 | .def( | |
238 | "open", | |
239 | (void (*)( | |
240 | tag::title(std::string), | |
241 | tag::width*(unsigned), | |
242 | tag::height*(unsigned)) | |
243 | )0 | |
244 | ); | |
245 | ||
246 | or at least: | |
247 | ||
248 | class_<window>("window") | |
249 | .def( | |
250 | "open", | |
251 | mpl::vector< | |
252 | void, | |
253 | tag::title(std::string), | |
254 | tag::width*(unsigned), | |
255 | tag::height*(unsigned) | |
256 | >() | |
257 | ); | |
258 | ||
259 | assuming, that is, that we will have to repeat the tags (yes, | |
260 | users of broken compilers will have to give us function pointer | |
261 | types instead). | |
262 | ||
263 | ------------------------------------------------------------------------------ | |
264 | ||
265 | concept |ParameterSpec| | |
266 | ----------------------- | |
267 | ||
268 | A |ParameterSpec| is a function type ``K(T)`` that describes both the keyword tag, | |
269 | ``K``, and the argument type, ``T``, for a parameter. | |
270 | ||
271 | ``K`` is either: | |
272 | ||
273 | * A *required* keyword of the form ``Tag`` | |
274 | * **or**, an *optional* keyword of the form ``Tag*`` | |
275 | * **or**, a *special* keyword of the form ``Tag**`` | |
276 | ||
277 | where ``Tag`` is a keyword tag type, as used in a specialization | |
278 | of |keyword|__. | |
279 | ||
280 | .. |keyword| replace:: ``boost::parameter::keyword`` | |
281 | __ ../../../parameter/doc/html/reference.html#keyword | |
282 | ||
283 | The **arity range** for an `MPL Sequence`_ of |ParameterSpec|'s is | |
284 | defined as the closed range: | |
285 | ||
286 | .. parsed-literal:: | |
287 | ||
288 | [ mpl::size<S> - number of *special* keyword tags in ``S``, mpl::size<S> ] | |
289 | ||
290 | For example, the **arity range** of ``mpl::vector2<x(int),y(int)>`` is ``[2,2]``, | |
291 | the **arity range** of ``mpl::vector2<x(int),y*(int)>`` is ``[2,2]`` and the | |
292 | **arity range** of ``mpl::vector2<x(int),y**(int)>`` is ``[1,2]``. | |
293 | ||
294 | ||
295 | ||
296 | *special* keywords | |
297 | --------------------------------- | |
298 | ||
299 | Sometimes it is desirable to have a default value for a parameter that differ | |
300 | in type from the parameter. This technique is useful for doing simple tag-dispatching | |
301 | based on the presence of a parameter. For example: | |
302 | ||
303 | .. An example_ of this is given in the Boost.Parameter | |
304 | docs. The example uses a different technique, but could also have been written like this: | |
305 | ||
306 | .. parsed-literal:: | |
307 | ||
308 | namespace core | |
309 | { | |
310 | template <class ArgumentPack> | |
311 | void dfs_dispatch(ArgumentPack const& args, mpl::false\_) | |
312 | { | |
313 | *…compute and use default color map…* | |
314 | } | |
315 | ||
316 | template <class ArgumentPack, class ColorMap> | |
317 | void dfs_dispatch(ArgumentPack const& args, ColorMap colormap) | |
318 | { | |
319 | *…use colormap…* | |
320 | } | |
321 | } | |
322 | ||
323 | template <class ArgumentPack> | |
324 | void depth_first_search(ArgumentPack const& args) | |
325 | { | |
326 | core::dfs_dispatch(args, args[color | mpl::false_()]); | |
327 | } | |
328 | ||
329 | .. @example.prepend(''' | |
330 | #include <boost/parameter/keyword.hpp> | |
331 | #include <boost/parameter/parameters.hpp> | |
332 | #include <boost/mpl/bool.hpp> | |
333 | #include <cassert> | |
334 | ||
335 | BOOST_PARAMETER_KEYWORD(tag, color); | |
336 | ||
337 | typedef boost::parameter::parameters<tag::color> params; | |
338 | ||
339 | namespace mpl = boost::mpl; | |
340 | ''') | |
341 | ||
342 | .. @example.replace_emphasis(''' | |
343 | assert(args[color | 1] == 1); | |
344 | ''') | |
345 | ||
346 | .. @example.replace_emphasis(''' | |
347 | assert(args[color | 1] == 0); | |
348 | ''') | |
349 | ||
350 | .. @example.append(''' | |
351 | int main() | |
352 | { | |
353 | depth_first_search(params()()); | |
354 | depth_first_search(params()(color = 0)); | |
355 | }''') | |
356 | ||
357 | .. @build() | |
358 | ||
359 | .. .. _example: index.html#dispatching-based-on-the-presence-of-a-default | |
360 | ||
361 | In the above example the type of the default for ``color`` is ``mpl::false_``, a | |
362 | type that is distinct from any color map that the user might supply. | |
363 | ||
364 | When binding the case outlined above, the default type for ``color`` will not | |
365 | be convertible to the parameter type. Therefore we need to tag the ``color`` | |
366 | keyword as a *special* keyword. This is done by specifying the tag as | |
367 | ``tag::color**`` when binding the function (see `concept ParameterSpec`_ for | |
368 | more details on the tagging). By doing this we tell the binding functions that | |
369 | it needs to generate two overloads, one with the ``color`` parameter present | |
370 | and one without. Had there been two *special* keywords, four overloads would | |
371 | need to be generated. The number of generated overloads is equal to 2\ | |
372 | :sup:`N`, where ``N`` is the number of *special* keywords. | |
373 | ||
374 | ------------------------------------------------------------------------------ | |
375 | ||
376 | class template ``init`` | |
377 | ----------------------- | |
378 | ||
379 | Defines a named parameter enabled constructor. | |
380 | ||
381 | .. parsed-literal:: | |
382 | ||
383 | template <class ParameterSpecs> | |
384 | struct init : python::def_visitor<init<ParameterSpecs> > | |
385 | { | |
386 | template <class Class> | |
387 | void def(Class& class\_); | |
388 | ||
389 | template <class CallPolicies> | |
390 | *def\_visitor* operator[](CallPolicies const& policies) const; | |
391 | }; | |
392 | ||
393 | .. @ignore() | |
394 | ||
395 | ``init`` requirements | |
396 | ~~~~~~~~~~~~~~~~~~~~~ | |
397 | ||
398 | * ``ParameterSpecs`` is an `MPL sequence`_ where each element is a | |
399 | model of |ParameterSpec|. | |
400 | * For every ``N`` in ``[U,V]``, where ``[U,V]`` is the **arity | |
401 | range** of ``ParameterSpecs``, ``Class`` must support these | |
402 | expressions: | |
403 | ||
404 | ======================= ============= ========================================= | |
405 | Expression Return type Requirements | |
406 | ======================= ============= ========================================= | |
407 | ``Class(a0, …, aN)`` \- ``a0``\ …\ ``aN`` are tagged arguments. | |
408 | ======================= ============= ========================================= | |
409 | ||
410 | ||
411 | ||
412 | ``template <class CallPolicies> operator[](CallPolicies const&)`` | |
413 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
414 | ||
415 | Returns a ``def_visitor`` equivalent to ``*this``, except that it | |
416 | uses CallPolicies when creating the binding. | |
417 | ||
418 | ||
419 | Example | |
420 | ~~~~~~~ | |
421 | ||
422 | .. parsed-literal:: | |
423 | ||
424 | #include <boost/parameter/keyword.hpp> | |
425 | #include <boost/parameter/preprocessor.hpp> | |
426 | #include <boost/parameter/python.hpp> | |
427 | #include <boost/python.hpp> | |
428 | #include <boost/mpl/vector.hpp> | |
429 | ||
430 | BOOST_PARAMETER_KEYWORD(tag, x) | |
431 | BOOST_PARAMETER_KEYWORD(tag, y) | |
432 | ||
433 | struct base | |
434 | { | |
435 | template <class ArgumentPack> | |
436 | base(ArgumentPack const& args) | |
437 | { | |
438 | *… use args …* | |
439 | } | |
440 | }; | |
441 | ||
442 | class X : base | |
443 | { | |
444 | public: | |
445 | BOOST_PARAMETER_CONSTRUCTOR(X, (base), tag, | |
446 | (required (x, \*)) | |
447 | (optional (y, \*)) | |
448 | ) | |
449 | }; | |
450 | ||
451 | BOOST_PYTHON_MODULE(*module name*) | |
452 | { | |
453 | using namespace boost::python; | |
454 | namespace py = boost::parameter::python; | |
455 | namespace mpl = boost::mpl; | |
456 | ||
457 | class_<X>("X", no_init) | |
458 | .def( | |
459 | py::init< | |
460 | mpl::vector<tag::x(int), tag::y\*(int)> | |
461 | >() | |
462 | ); | |
463 | } | |
464 | ||
465 | .. @example.replace_emphasis(''' | |
466 | assert(args[x] == 0); | |
467 | assert(args[y | 1] == 1); | |
468 | ''') | |
469 | ||
470 | .. @example.replace_emphasis('my_module') | |
471 | ||
472 | .. @jam_prefix.append('import python ;') | |
473 | .. @jam_prefix.append('stage . : my_module /boost/python//boost_python ;') | |
474 | .. @my_module = build( | |
475 | output = 'my_module' | |
476 | , target_rule = 'python-extension' | |
477 | , input = '/boost/python//boost_python' | |
478 | ) | |
479 | ||
480 | ------------------------------------------------------------------------------ | |
481 | ||
482 | class template ``call`` | |
483 | ----------------------- | |
484 | ||
485 | Defines a ``__call__`` operator, mapped to ``operator()`` in C++. | |
486 | ||
487 | .. parsed-literal:: | |
488 | ||
489 | template <class ParameterSpecs> | |
490 | struct call : python::def_visitor<call<ParameterSpecs> > | |
491 | { | |
492 | template <class Class> | |
493 | void def(Class& class\_); | |
494 | ||
495 | template <class CallPolicies> | |
496 | *def\_visitor* operator[](CallPolicies const& policies) const; | |
497 | }; | |
498 | ||
499 | .. @ignore() | |
500 | ||
501 | ``call`` requirements | |
502 | ~~~~~~~~~~~~~~~~~~~~~ | |
503 | ||
504 | * ``ParameterSpecs`` is an `MPL sequence`_ where each element | |
505 | except the first models |ParameterSpec|. The first element | |
506 | is the result type of ``c(…)``. | |
507 | * ``Class`` must support these expressions, where ``c`` is an | |
508 | instance of ``Class``: | |
509 | ||
510 | =================== ==================== ======================================= | |
511 | Expression Return type Requirements | |
512 | =================== ==================== ======================================= | |
513 | ``c(a0, …, aN)`` Convertible to ``R`` ``a0``\ …\ ``aN`` are tagged arguments. | |
514 | =================== ==================== ======================================= | |
515 | ||
516 | For every ``N`` in ``[U,V]``, where ``[U,V]`` is the **arity range** of ``ParameterSpecs``. | |
517 | ||
518 | ||
519 | ``template <class CallPolicies> operator[](CallPolicies const&)`` | |
520 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
521 | ||
522 | Returns a ``def_visitor`` equivalent to ``*this``, except that it | |
523 | uses CallPolicies when creating the binding. | |
524 | ||
525 | ||
526 | Example | |
527 | ~~~~~~~ | |
528 | ||
529 | .. parsed-literal:: | |
530 | ||
531 | #include <boost/parameter/keyword.hpp> | |
532 | #include <boost/parameter/preprocessor.hpp> | |
533 | #include <boost/parameter/python.hpp> | |
534 | #include <boost/python.hpp> | |
535 | #include <boost/mpl/vector.hpp> | |
536 | ||
537 | BOOST_PARAMETER_KEYWORD(tag, x) | |
538 | BOOST_PARAMETER_KEYWORD(tag, y) | |
539 | ||
540 | namespace parameter = boost::parameter; | |
541 | ||
542 | typedef parameter::parameters< | |
543 | parameter::required<tag::x> | |
544 | , parameter::optional<tag::y> | |
545 | > call_parameters; | |
546 | ||
547 | class X | |
548 | { | |
549 | public: | |
550 | template <class ArgumentPack> | |
551 | int call_impl(ArgumentPack const& args) | |
552 | { | |
553 | *… use args …* | |
554 | } | |
555 | ||
556 | template <class A0> | |
557 | int operator()(A0 const& a0) | |
558 | { | |
559 | return call_impl(call_parameters()(a0)); | |
560 | } | |
561 | ||
562 | template <class A0, class A1> | |
563 | int operator()(A0 const& a0, A1 const& a1) | |
564 | { | |
565 | return call_impl(call_parameters()(a0,a1)); | |
566 | } | |
567 | }; | |
568 | ||
569 | BOOST_PYTHON_MODULE(*module name*) | |
570 | { | |
571 | using namespace boost::python; | |
572 | namespace py = parameter::python; | |
573 | namespace mpl = boost::mpl; | |
574 | ||
575 | class_<X>("X") | |
576 | .def( | |
577 | py::call< | |
578 | mpl::vector<int, tag::x(int), tag::y\*(int)> | |
579 | >() | |
580 | ); | |
581 | } | |
582 | ||
583 | .. @example.replace_emphasis(''' | |
584 | assert(args[x] == 0); | |
585 | assert(args[y | 1] == 1); | |
586 | return 0; | |
587 | ''') | |
588 | ||
589 | .. @example.replace_emphasis('my_module') | |
590 | ||
591 | .. @my_module = build( | |
592 | output = 'my_module' | |
593 | , target_rule = 'python-extension' | |
594 | , input = '/boost/python//boost_python' | |
595 | ) | |
596 | ||
597 | ------------------------------------------------------------------------------ | |
598 | ||
599 | class template ``function`` | |
600 | --------------------------- | |
601 | ||
602 | Defines a named parameter enabled member function. | |
603 | ||
604 | .. parsed-literal:: | |
605 | ||
606 | template <class Fwd, class ParameterSpecs> | |
607 | struct function : python::def_visitor<function<Fwd, ParameterSpecs> > | |
608 | { | |
609 | template <class Class, class Options> | |
610 | void def(Class& class\_, char const* name, Options const& options); | |
611 | }; | |
612 | ||
613 | .. @ignore() | |
614 | ||
615 | ``function`` requirements | |
616 | ~~~~~~~~~~~~~~~~~~~~~~~~~ | |
617 | ||
618 | * ``ParameterSpecs`` is an `MPL sequence`_ where each element | |
619 | except the first models |ParameterSpec|. The first element | |
620 | is the result type of ``c.f(…)``, where ``f`` is the member | |
621 | function. | |
622 | * An instance of ``Fwd`` must support this expression: | |
623 | ||
624 | ============================================ ==================== ================================================= | |
625 | Expression Return type Requirements | |
626 | ============================================ ==================== ================================================= | |
627 | ``fwd(boost::type<R>(), self, a0, …, aN)`` Convertible to ``R`` ``self`` is a reference to the object on which | |
628 | the function should be invoked. ``a0``\ …\ ``aN`` | |
629 | are tagged arguments. | |
630 | ============================================ ==================== ================================================= | |
631 | ||
632 | For every ``N`` in ``[U,V]``, where ``[U,V]`` is the **arity range** of ``ParameterSpecs``. | |
633 | ||
634 | ||
635 | Example | |
636 | ~~~~~~~ | |
637 | ||
638 | This example exports a member function ``f(int x, int y = …)`` to Python. The | |
639 | sequence of |ParameterSpec|'s ``mpl::vector2<tag::x(int), tag::y*(int)>`` has | |
640 | an **arity range** of [2,2], so we only need one forwarding overload. | |
641 | ||
642 | .. parsed-literal:: | |
643 | ||
644 | #include <boost/parameter/keyword.hpp> | |
645 | #include <boost/parameter/preprocessor.hpp> | |
646 | #include <boost/parameter/python.hpp> | |
647 | #include <boost/python.hpp> | |
648 | #include <boost/mpl/vector.hpp> | |
649 | ||
650 | BOOST_PARAMETER_KEYWORD(tag, x) | |
651 | BOOST_PARAMETER_KEYWORD(tag, y) | |
652 | ||
653 | class X | |
654 | { | |
655 | public: | |
656 | BOOST_PARAMETER_MEMBER_FUNCTION((void), f, tag, | |
657 | (required (x, \*)) | |
658 | (optional (y, \*, 1)) | |
659 | ) | |
660 | { | |
661 | *…* | |
662 | } | |
663 | }; | |
664 | ||
665 | struct f_fwd | |
666 | { | |
667 | template <class A0, class A1> | |
668 | void operator()(boost::type<void>, X& self, A0 const& a0, A1 const& a1) | |
669 | { | |
670 | self.f(a0, a1); | |
671 | } | |
672 | }; | |
673 | ||
674 | BOOST_PYTHON_MODULE(*module name*) | |
675 | { | |
676 | using namespace boost::python; | |
677 | namespace py = boost::parameter::python; | |
678 | namespace mpl = boost::mpl; | |
679 | ||
680 | class_<X>("X") | |
681 | .def("f", | |
682 | py::function< | |
683 | f_fwd | |
684 | , mpl::vector<void, tag::x(int), tag::y\*(int)> | |
685 | >() | |
686 | ); | |
687 | } | |
688 | ||
689 | .. @example.replace_emphasis(''' | |
690 | assert(x == 0); | |
691 | assert(y == 1); | |
692 | ''') | |
693 | ||
694 | .. @example.replace_emphasis('my_module') | |
695 | ||
696 | .. @my_module = build( | |
697 | output = 'my_module' | |
698 | , target_rule = 'python-extension' | |
699 | , input = '/boost/python//boost_python' | |
700 | ) | |
701 | ||
702 | ------------------------------------------------------------------------------ | |
703 | ||
704 | function template ``def`` | |
705 | ------------------------- | |
706 | ||
707 | Defines a named parameter enabled free function in the current Python scope. | |
708 | ||
709 | .. parsed-literal:: | |
710 | ||
711 | template <class Fwd, class ParameterSpecs> | |
712 | void def(char const* name); | |
713 | ||
714 | .. @ignore() | |
715 | ||
716 | ``def`` requirements | |
717 | ~~~~~~~~~~~~~~~~~~~~ | |
718 | ||
719 | * ``ParameterSpecs`` is an `MPL sequence`_ where each element | |
720 | except the first models |ParameterSpec|. The first element | |
721 | is the result type of ``f(…)``, where ``f`` is the function. | |
722 | * An instance of ``Fwd`` must support this expression: | |
723 | ||
724 | ====================================== ==================== ======================================= | |
725 | Expression Return type Requirements | |
726 | ====================================== ==================== ======================================= | |
727 | ``fwd(boost::type<R>(), a0, …, aN)`` Convertible to ``R`` ``a0``\ …\ ``aN`` are tagged arguments. | |
728 | ====================================== ==================== ======================================= | |
729 | ||
730 | For every ``N`` in ``[U,V]``, where ``[U,V]`` is the **arity range** of ``ParameterSpecs``. | |
731 | ||
732 | ||
733 | Example | |
734 | ~~~~~~~ | |
735 | ||
736 | This example exports a function ``f(int x, int y = …)`` to Python. The | |
737 | sequence of |ParameterSpec|'s ``mpl::vector2<tag::x(int), tag::y*(int)>`` has | |
738 | an **arity range** of [2,2], so we only need one forwarding overload. | |
739 | ||
740 | .. parsed-literal:: | |
741 | ||
742 | BOOST_PARAMETER_FUNCTION((void), f, tag, | |
743 | (required (x, \*)) | |
744 | (optional (y, \*, 1)) | |
745 | ) | |
746 | { | |
747 | *…* | |
748 | } | |
749 | ||
750 | struct f_fwd | |
751 | { | |
752 | template <class A0, class A1> | |
753 | void operator()(boost::type<void>, A0 const& a0, A1 const& a1) | |
754 | { | |
755 | f(a0, a1); | |
756 | } | |
757 | }; | |
758 | ||
759 | BOOST_PYTHON_MODULE(…) | |
760 | { | |
761 | def< | |
762 | f_fwd | |
763 | , mpl::vector< | |
764 | void, tag::\ x(int), tag::\ y\*(int) | |
765 | > | |
766 | >("f"); | |
767 | } | |
768 | ||
769 | .. @ignore() | |
770 | ||
771 | .. again, the undefined ``fwd`` identifier. | |
772 | ||
773 | Portability | |
774 | ----------- | |
775 | ||
776 | The Boost.Parameter Python binding library requires *partial template | |
777 | specialization*. | |
778 |