diff --git a/doc/python.rst b/doc/python.rst index bf2d35f..f929ee7 100755 --- a/doc/python.rst +++ b/doc/python.rst @@ -52,21 +52,13 @@ must be specified. Additionally, because Boost.Parameter enabled functions are templates, the desired function signature must be specified. -.. Always diff my edited version with the original to see what I -.. changed, and think about why I changed it. Ask if you don't -.. understand. "Boost.Parameter-enabled" needs that hyphen -.. everywhere. I'm leaving that change to you. - -.. Why must keyword tags be specified again? Ah, because we didn't -.. record their association with the wrapped function in the first -.. place. I think that should be possible, no? - The keyword tags are specified as an `MPL Sequence`_, using the pointer qualifications described in |KeywordsSpec|_ below. The signature is also specifid as an `MPL sequence`_ of parameter -types. Additional data may be needed in the signature sequence by -specific binding utilities. For example, ``function`` requires the -return type to be part of the signature sequence. +types. Additionally, ``boost::parameter::python::function`` and +``boost::parameter::python::def`` requires a class with forwarding +overloads. We will take a closer look at how this is done in the +tutorial section below. .. The last two sentences are terribly vague. Which namespace is .. ``function`` in? Isn't the return type always needed? What @@ -74,19 +66,24 @@ return type to be part of the signature sequence. .. function? .. _`MPL Sequence`: ../../../mpl/doc/refmanual/sequences.html +.. _keywordsspec: `concept KeywordsSpec`_ Tutorial -------- In this section we will outline the steps needed to bind a simple -Boost.Parameter enabled member function to Python. Knowledge of the -Boost.Parameter macros are required to understand this section. +Boost.Parameter-enabled member function to Python. Knowledge of the +Boost.Parameter macros_ are required to understand this section. -.. Link to the docs for Boost.Parameter macros +.. _macros: index.html The class and member function we are interested in binding looks like this:: + #include + #include + #include + // First the keywords BOOST_PARAMETER_KEYWORD(tag, title) BOOST_PARAMETER_KEYWORD(tag, width) @@ -100,16 +97,51 @@ like this:: (required (title, (std::string))) (optional (width, (unsigned), 400) (height, (unsigned), 400)) - ); + ) + { + … + } }; -.. Don't use endline layout. +It defines a set of overloaded member functions called ``open`` with one +required parameter and two optional ones. To bind this member function to +Python we use the binding utility ``boost::parameter::python::function``. +``boost::parameter::python::function`` is a def_visitor_ that we'll instantiate +and pass to ``boost::python::class_::def()``. -It defines a set of overloaded member functions called ``open`` -with one required parameter and two optional ones. To bind this -member function to Python we use the binding utility -``function``. ``function`` is a def_visitor_ that we'll -instantiate and pass to ``boost::python::class_::def()``. +To use ``boost::parameter::python::function`` we first need to define +a class with forwarding overloads. + +:: + + struct open_fwd + { + template + void operator()( + boost::type, window& self, A0 const& a0, A1 const& a1, A2 const& a2 + ) + { + self.open(a0, a1, a2); + } + }; + +The first parameter, ``boost::type``, tells the forwarding overload +what the return type should be. In this case we know that it's always void +but in some cases, when we are exporting several specializations of a +Boost.Parameter-enabled template, we need to use that parameter to +deduce the return type. + +``window::open()`` takes a total of 3 parameters, so the forwarding function +needs to take three parameters as well. + +.. Note:: + + We only need one overload in the forwarding class, despite the + fact that there are two optional parameters. There are special + circumstances when several overload are needed; see + `special keywords`_. + +Next we'll define the module and export the class: :: @@ -121,21 +153,51 @@ instantiate and pass to ``boost::python::class_::def()``. class_("window") .def( "open", py::function< - mpl::vector, - mpl::vector + open_fwd + , mpl::vector + , mpl::vector >() ); } -.. you missed passing the first argument, open_fwd, I think? +.. @jam_prefix.append('import python ;') +.. @jam_prefix.append('stage . : my_module /boost/python//boost_python ;') +.. @my_module = build( + output = 'my_module' + , target_rule = 'python-extension' + , input = '/boost/python//boost_python' + , howmany = 'all' + ) -.. be consistent in indentation and comma placement. Pick either -.. leading or trailing commas. +.. @del jam_prefix[-1:] + +``py::function`` is passed three parameters. The first one is the class +with forwarding overloads that we defined earlier. The second one is +an `MPL Sequence`_ with the keyword tag types for the function. The +pointer syntax means that the parameter is optional, so in this case +``width`` and ``height`` are optional parameters. The third parameter +is an `MPL Sequence`_ with the desired function signature. The return type comes first, and +then the parameter types: + +.. parsed-literal:: + + mpl::vector + *return type* *title* *width* *height* + +.. @ignore() + +That's it! This class can now be used in Python with the expected syntax:: + + >>> w = my_module.window() + >>> w.open(title = "foo", height = 20) + +.. @example.prepend('import my_module') +.. @run_python(module_path = my_module) .. Sorry to say this at such a late date, but this syntax really .. strikes me as cumbersome. Couldn't we do something like: - class_("window") + class_("window") .def( "open", (void (*)( @@ -162,6 +224,8 @@ instantiate and pass to ``boost::python::class_::def()``. users of broken compilers will have to give us function pointer types instead). +------------------------------------------------------------------------------ + concept |KeywordsSpec| ---------------------- @@ -171,10 +235,10 @@ A |KeywordsSpec| is an `MPL sequence`_ where each element is either: * **or**, an *optional* keyword of the form ``K*`` * **or**, a *special* keyword of the form ``K**`` -where ``K`` is a specialization of ``boost::parameter::keyword``__. - +where ``K`` is a keyword tag type, as used in a specialization +of boost::parameter::keyword__. -.. __ ../../../parameter/doc/html/reference.html#keyword +__ ../../../parameter/doc/html/reference.html#keyword The **arity range** of a |KeywordsSpec| is defined as the closed range: @@ -189,7 +253,7 @@ For example, the **arity range** of ``mpl::vector2`` is [2,2], the **arity .. Don't optional keywords affect the arity range? -*special* keyword tags +*special* keywords --------------------------------- Sometimes it is desirable to have a default value for a parameter that differ @@ -219,11 +283,6 @@ docs. The example uses a different technique, but could also have been written l .. _example: index.html#dispatching-based-on-the-presence-of-a-default -.. there have been several mistakes in these code examples. I -.. built a literate programming system for ReST, which we used for -.. the MPL book. If you'd like I'll check it in and you can use it -.. to check these. - In the above example the type of the default for ``color`` is ``mpl::false_``, a type that is distinct from any color map that the user might supply. @@ -235,10 +294,6 @@ present and one without. Had there been two *special* keywords, four overloads would need to be generated. The number of generated overloads is equal to ``2^N``, where ``N`` is the number of *special* keywords. -.. The entire section below was rewritten. - -.. No need to leave commented out detritus in the document. That's -.. what source control is for. ------------------------------------------------------------------------------ @@ -266,11 +321,11 @@ Defines a named parameter enabled constructor. range** of ``Keywords``, ``Class`` must support these expressions: - ======================================================= ==================== ============================================== - Expression Return type Requirements - ======================================================= ==================== ============================================== - ``Class(a0, ..., aN)`` \- ``a0``..\ ``aN`` are tagged arguments. - ======================================================= ==================== ============================================== + ======================= ============= ========================================= + Expression Return type Requirements + ======================= ============= ========================================= + ``Class(a0, ..., aN)`` \- ``a0``..\ ``aN`` are tagged arguments. + ======================= ============= ========================================= .. Limit the width of these table cells. Some rst backend .. processors actually produce different results depending on the @@ -329,11 +384,11 @@ Defines a ``__call__`` operator, mapped to ``operator()`` in C++. in the order dictated by ``Keywords``, and the return type prepended. * ``Class`` must support these expressions, where ``c`` is an instance of ``Class``: - ======================================================= ==================== ============================================== - Expression Return type Requirements - ======================================================= ==================== ============================================== - ``c(a0, ..., aN)`` Convertible to ``R`` ``a0``..\ ``aN`` are tagged arguments. - ======================================================= ==================== ============================================== + =================== ==================== ======================================= + Expression Return type Requirements + =================== ==================== ======================================= + ``c(a0, ..., aN)`` Convertible to ``R`` ``a0``..\ ``aN`` are tagged arguments. + =================== ==================== ======================================= For every ``N`` in ``[U,V]``, where ``[U,V]`` is the **arity range** of ``Keywords``. @@ -404,13 +459,13 @@ Defines a named parameter enabled member function. in the order dictated by ``Keywords``, and the return type prepended. * An instance of ``Fwd`` must support this expression: - ======================================================= ==================== ============================================== - Expression Return type Requirements - ======================================================= ==================== ============================================== - ``fwd(boost::type(), self, a0, ..., aN)`` Convertible to ``R`` ``self`` is a reference to the object on which - the function should be invoked. ``a0``..\ ``aN`` - are tagged arguments. - ======================================================= ==================== ============================================== + ============================================ ==================== ============================================== + Expression Return type Requirements + ============================================ ==================== ============================================== + ``fwd(boost::type(), self, a0, …, aN)`` Convertible to ``R`` ``self`` is a reference to the object on which + the function should be invoked. ``a0``…``aN`` + are tagged arguments. + ============================================ ==================== ============================================== For every ``N`` in ``[U,V]``, where ``[U,V]`` is the **arity range** of ``Keywords``. @@ -418,7 +473,7 @@ Defines a named parameter enabled member function. Example ~~~~~~~ -This example exports a member function ``f(int x, int y = ..)`` to Python. +This example exports a member function ``f(int x, int y = …)`` to Python. The |KeywordsSpec| ``mpl::vector2`` has an **arity range** of [2,2], so we only need one forwarding overload. @@ -432,7 +487,7 @@ of [2,2], so we only need one forwarding overload. (optional (y, \*)) ) { - /\* .. \*/ + /\* … \*/ } }; @@ -450,7 +505,7 @@ of [2,2], so we only need one forwarding overload. class_("X") .def("f", function< - fwd + f_fwd , mpl::vector2 , mpl::vector3 >() @@ -481,11 +536,11 @@ Defines a named parameter enabled free function in the current Python scope. prepended. * An instance of ``Fwd`` must support this expression: - ======================================================= ==================== ============================================== - Expression Return type Requirements - ======================================================= ==================== ============================================== - ``fwd(boost::type(), a0, ..., aN)`` Convertible to ``R`` ``a0``..\ ``aN`` are tagged arguments. - ======================================================= ==================== ============================================== + ====================================== ==================== ====================================== + Expression Return type Requirements + ====================================== ==================== ====================================== + ``fwd(boost::type(), a0, …, aN)`` Convertible to ``R`` ``a0``…``aN`` are tagged arguments. + ====================================== ==================== ====================================== For every ``N`` in ``[U,V]``, where ``[U,V]`` is the **arity range** of ``Keywords``. @@ -493,7 +548,7 @@ Defines a named parameter enabled free function in the current Python scope. Example ~~~~~~~ -This example exports a function ``f(int x, int y = ...)`` to Python. +This example exports a function ``f(int x, int y = …)`` to Python. The |KeywordsSpec| ``mpl::vector2`` has an **arity range** of [2,2], so we only need one forwarding overload. @@ -504,7 +559,7 @@ of [2,2], so we only need one forwarding overload. (optional (y, \*)) ) { - /\* .. \*/ + /\* … \*/ } struct f_fwd @@ -516,10 +571,10 @@ of [2,2], so we only need one forwarding overload. } }; - BOOST_PYTHON_MODULE(..) + BOOST_PYTHON_MODULE(…) { def< - fwd + f_fwd , mpl::vector2 , mpl::vector3 >("f"); @@ -533,4 +588,4 @@ Portability The Boost.Parameter Python binding library requires *partial template specialization*. .. Oh. In that case, we don't have to worry so much about -.. compilers that can't parse function types. \ No newline at end of file +.. compilers that can't parse function types.