]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/parameter/doc/python.rst
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / parameter / doc / python.rst
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