]> git.proxmox.com Git - ceph.git/blame - 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
CommitLineData
7c673cae
FG
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
42Introduction
43------------
44
45``boost/parameter/python.hpp`` introduces a group of |def_visitors|_ that can
46be used to easily expose Boost.Parameter-enabled member functions to Python with
47Boost.Python. It also provides a function template ``def()`` that can be used
48to 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
56When binding a Boost.Parameter enabled function, the keyword tags
57must be specified. Additionally, because Boost.Parameter enabled
58functions are templates, the desired function signature must be
59specified.
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
69The keyword tags and associated argument types are specified as an `MPL
70Sequence`_, using the function type syntax described in |ParameterSpec|_
71below. Additionally, ``boost::parameter::python::function`` and
72``boost::parameter::python::def`` requires a class with forwarding overloads.
73We 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
83Tutorial
84--------
85
86In this section we will outline the steps needed to bind a simple
87Boost.Parameter-enabled member function to Python. Knowledge of the
88Boost.Parameter macros_ are required to understand this section.
89
90.. _macros: index.html
91
92The class and member function we are interested in binding looks
93like 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
128It defines a set of overloaded member functions called ``open`` with one
129required parameter and two optional ones. To bind this member function to
130Python we use the binding utility ``boost::parameter::python::function``.
131``boost::parameter::python::function`` is a |def_visitor|_ that we'll instantiate
132and pass to ``boost::python::class_::def()``.
133
134To use ``boost::parameter::python::function`` we first need to define
135a class with forwarding overloads. This is needed because ``window::open()``
136is 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
152The first parameter, ``boost::type<void>``, tells the forwarding overload
153what the return type should be. In this case we know that it's always void
154but in some cases, when we are exporting several specializations of a
155Boost.Parameter-enabled template, we need to use that parameter to
156deduce the return type.
157
158``window::open()`` takes a total of 3 parameters, so the forwarding function
159needs 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
168Next 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
204forwarding overloads that we defined earlier. The second one is an `MPL
205Sequence`_ with the keyword tag types and argument types for the function
206specified as function types. The pointer syntax used in ``tag::width*`` and
207``tag::height*`` means that the parameter is optional. The first element of
208the `MPL Sequence`_ is the return type of the function, in this case ``void``,
209which is passed as the first argument to ``operator()`` in the forwarding
210class.
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
225That'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
265concept |ParameterSpec|
266-----------------------
267
268A |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
277where ``Tag`` is a keyword tag type, as used in a specialization
278of |keyword|__.
279
280.. |keyword| replace:: ``boost::parameter::keyword``
281__ ../../../parameter/doc/html/reference.html#keyword
282
283The **arity range** for an `MPL Sequence`_ of |ParameterSpec|'s is
284defined as the closed range:
285
286.. parsed-literal::
287
288 [ mpl::size<S> - number of *special* keyword tags in ``S``, mpl::size<S> ]
289
290For example, the **arity range** of ``mpl::vector2<x(int),y(int)>`` is ``[2,2]``,
291the **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
299Sometimes it is desirable to have a default value for a parameter that differ
300in type from the parameter. This technique is useful for doing simple tag-dispatching
301based 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
361In the above example the type of the default for ``color`` is ``mpl::false_``, a
362type that is distinct from any color map that the user might supply.
363
364When binding the case outlined above, the default type for ``color`` will not
365be convertible to the parameter type. Therefore we need to tag the ``color``
366keyword as a *special* keyword. This is done by specifying the tag as
367``tag::color**`` when binding the function (see `concept ParameterSpec`_ for
368more details on the tagging). By doing this we tell the binding functions that
369it needs to generate two overloads, one with the ``color`` parameter present
370and one without. Had there been two *special* keywords, four overloads would
371need 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
376class template ``init``
377-----------------------
378
379Defines 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
415Returns a ``def_visitor`` equivalent to ``*this``, except that it
416uses CallPolicies when creating the binding.
417
418
419Example
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
482class template ``call``
483-----------------------
484
485Defines 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
522Returns a ``def_visitor`` equivalent to ``*this``, except that it
523uses CallPolicies when creating the binding.
524
525
526Example
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
599class template ``function``
600---------------------------
601
602Defines 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
635Example
636~~~~~~~
637
638This example exports a member function ``f(int x, int y = …)`` to Python. The
639sequence of |ParameterSpec|'s ``mpl::vector2<tag::x(int), tag::y*(int)>`` has
640an **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
704function template ``def``
705-------------------------
706
707Defines 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
733Example
734~~~~~~~
735
736This example exports a function ``f(int x, int y = …)`` to Python. The
737sequence of |ParameterSpec|'s ``mpl::vector2<tag::x(int), tag::y*(int)>`` has
738an **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
773Portability
774-----------
775
776The Boost.Parameter Python binding library requires *partial template
777specialization*.
778