Boost Parameter 庫 Python 綁定文檔

作者: Daniel Wallin
聯繫方式: dalwan01@student.umu.se
組織: Boost Consulting
日期: 2008-03-22
版權: Copyright David Abrahams, Daniel Wallin 2005. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

摘要

Makes it possible to bind Boost.Parameter-enabled functions, operators and constructors to Python. 使我們可以將 Boost.Parameter 式 (Boost.Parameter-enabled) 的函數,操作符和構造函數綁定到 Python。

Boost

Contents 目錄

Introduction 介紹

boost/parameter/python.hpp introduces a group of def_visitors that can be used to easily expose Boost.Parameter-enabled member functions to Python with Boost.Python. It also provides a function template def() that can be used to expose Boost.Parameter-enabled free functions.

boost/parameter/python.hpp 引入了一 組 def_visitors, 使用 Boost.Python 庫,它們可以被用來狠方便的將 Boost.Parameter式 的成員函數暴露給 Python。也提供了一個函數模 板 def(),可以用來暴露那些 Boost.Parameter式 的自由函數(譯註:非成員函數)。

When binding a Boost.Parameter enabled function, the keyword tags must be specified. Additionally, because Boost.Parameter enabled functions are templates, the desired function signature must be specified.

在綁定一個 Boost.Parameter式 的函數時,關鍵字標籤(keyword tag)必須被指定。進一步講,由於 Boost.Parameter式 的函數是模板形式的, 期望的函數簽名(function signature)也必須被指定。

The keyword tags and associated argument types are specified as an MPL Sequence, using the function type syntax described in ParameterSpec below. 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.

關鍵字標籤和與其相關的參數類型都是由一個 MPL Sequence 指定的, 指定函數類型的語法在下面的 ParameterSpec 中有講到。 進一步講,boost::parameter::python::functionboost::parameter::python::def 都要求一個帶有 轉交重載函數(forwarding overload) 的類。 我們會在下面的教程章節中仔細講解這些是如何做到的。

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式 的成員函數到 Python 的步驟。要理解這一節,你需要 瞭解 Boost.Parameter 庫的 一些相關宏 的知識。

The class and member function we are interested in binding looks like this:

在綁定中過程,我們感興趣的類和成員函數看起來是這樣的:

#include <boost/parameter/keyword.hpp>
#include <boost/parameter/preprocessor.hpp>
#include <boost/parameter/python.hpp>
#include <boost/python.hpp>

// First the keywords 首先是關鍵字
BOOST_PARAMETER_KEYWORD(tag, title)
BOOST_PARAMETER_KEYWORD(tag, width)
BOOST_PARAMETER_KEYWORD(tag, height)

class window
{
public:
BOOST_PARAMETER_MEMBER_FUNCTION(
(void), open, tag,
(required (title, (std::string)))
(optional (width, (unsigned), 400)
(height, (unsigned), 400))
)
{
… function implementation 函數實現 … } };

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().

它定義了一組叫做 open 的重載成員函數,帶有一個 必選參變量(required parameter) 和 兩個 可選參變量(optional paramter)。要將這個成員函數綁定到 Python,我們使用綁定工具 boost::parameter::python::function

To use boost::parameter::python::function we first need to define a class with forwarding overloads.

要使用 boost::parameter::python::function,我們首先需要定義一個帶有 轉交重載函數(forwarding overload) 的類。

struct open_fwd
{
template <class A0, class A1, class A2>
void operator()(
boost::type<void>, window& self
, A0 const& a0, A1 const& a1, A2 const& a2
)
{
self.open(a0, a1, a2);
}
};

The first parameter, boost::type<void>, 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.

第一個參變量,boost::type<void>,告訴 轉交重載函數(forwarding overload) 返 回值的類型是什麼。在這裡,我們知道它就是 void,但是在某些情況下,當我們導出一個 Boost.Parameter式 模板的 特化版本(speicialization) 時,我們 需要使用這個參變量來推導返回類型。

window::open() takes a total of 3 parameters, so the forwarding function needs to take three parameters as well.

window::open() 一共帶三個參變量,因此 轉接函數(forwarding function) 也需要帶有三個參變量。

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.

儘管有兩個可選參變量(parameter),在 轉交類(forwarding class) 中我們只需要一個 重載函數(overload)。在某些特殊的環境下,會需要多個重載函數; 參見 特殊關鍵字(special keywords)

Next we'll define the module and export the class:

接下來,我們就可以定義模塊並導出類了:

BOOST_PYTHON_MODULE(my_module)
{
using namespace boost::python;
namespace py = boost::parameter::python;
namespace mpl = boost::mpl;

class_<window>("window")
.def(
"open", py::function<
open_fwd
, mpl::vector<
void
, tag::title(std::string)
, tag::width*(unsigned)
, tag::height*(unsigned)
>
>()
);
}

py::function is passed two 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 and argument types for the function specified as function types. The pointer syntax used in tag::width* and tag::height* means that the parameter is optional. The first element of the MPL Sequence is the return type of the function, in this case void.

有兩個參變量傳給了 py::function。第一個是我們早先定義的帶 有 轉交重載函數(forwarding overload) 的類。第二個是一帶有 關鍵字標籤類型(keyword tag type) 和 參數類型(被聲明為函數類型) 的 MPL Sequence。 在 tag::width*tag::height* 中 使用的指針(pointer)語法表示這個 參變量(parameter) 是可選的。MPL Sequence 中 的第一個元素是這個函數的返回類型,在這裡就是 void

That's it! This class can now be used in Python with the expected syntax:

好啦!現在這個類就可以在 Python 中用我們期望的語法使用了:

>>> w = my_module.window()
>>> w.open(title = "foo", height = 20)

概念 ParameterSpec

A ParameterSpec is a function type K(T) that describes both the keyword tag, K, and the argument type, T, for a parameter.

ParameterSpec 是一個 K(T) 式的函數類型,它描述 了一個參變量(parameter)的 關鍵字標籤(keyword tag) K,和 參數類型 T

K is either:

K 是下面之一:

where Tag is a keyword tag type, as used in a specialization of boost::parameter::keyword.

這裡 Tag 是一個關鍵字標籤類型(keyword tag type),就像 在 boost::parameter::keyword 裡規範的那樣使用。

The arity range for an MPL Sequence of ParameterSpec's is defined as the closed range:

一個 ParameterSpecMPL Sequence元數區間(arity range) 是由下面的全閉區間定義的:

[ mpl::size<S> - number of special keyword tags in S, mpl::size<S> ]
[ mpl::size<S> - S特殊關鍵字標籤(keyword tag)的個數 , mpl::size<S> ]
(譯註:也就是 [ 非特殊關鍵字標籤的個數 , 關鍵字標籤的個數 ] )

For example, the arity range of mpl::vector2<x(int),y(int)> is [2,2], the arity range of mpl::vector2<x(int),y*(int)> is [2,2] and the arity range of mpl::vector2<x(int),y**(int)> is [1,2].

比如,mpl::vector2<x(int),y(int)>元數區間(arity range)[2,2]mpl::vector2<x(int),y*(int)>元數區間(arity range)[2,2]mpl::vector2<x(int),y**(int)>元數區間(arity range)[1,2]

special keywords 特殊 關鍵字

Sometimes it is desirable to have a default value for a parameter that differ in type from the parameter. This technique is useful for doing simple tag-dispatching based on the presence of a parameter. An example of this is given in the Boost.Parameter docs. The example uses a different technique, but could also have been written like this:

有時候,我們希望能夠為參變量(parameter)賦一個默認值,但是這個默認值的類型不是參變量(parameter)的類型。 這種技術在基於現有參變量做一些簡單的 標籤分發(tag-dispatching) 的時候非常有用。 在 Boost.Parameter 的文檔裡面有一個這樣的 例子

namespace core
{
template <class ArgumentPack>
void dfs_dispatch(ArgumentPack const& args, mpl::false_)
{
…compute and use default color map 計算並使用默認的 color map … } template <class ArgumentPack, class ColorMap> void dfs_dispatch(ArgumentPack const& args, ColorMap colormap) { …use colormap 使用 colormap … } } template <class ArgumentPack> void depth_first_search(ArgumentPack const& args) { core::dfs_dispatch(args, args[color | mpl::false_()]); }

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.

在上面的這個例子裡面,color 默認值的類型是 mpl::false_,而這個類型是跟任何可能提供的 color map 的類型都不相同的。

When binding the case outlined above, the default type for color will not be convertible to the parameter type. Therefore we need to tag the color keyword as a special keyword. By doing this we tell the binding functions that it needs to generate two overloads, one with the color parameter 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 2N, where N is the number of special keywords.

在綁定上面列出的情況時,color 的默認值類型將不能轉化成參變量的類型。因此我們需要 將 color 標記為一個 特殊 關鍵字。這樣做之後,我們就是告訴綁定函數它可能需要 生成兩個重載函數,一個是帶有 color 參變量的,一個是沒有的。 要是有兩個 特殊 關鍵字,就需要生成四個重載函數。生成的重載函數的個數等於 2N,這 裡 N特殊 關鍵字的個數。


class template init 類模板 init

Defines a named parameter enabled constructor.

定義一個有名的 Parameter式 的構造函數。

template <class ParameterSpecs>
struct init : python::def_visitor<init<ParameterSpecs> >
{
template <class Class>
void def(Class& class_);

template <class CallPolicies>
def_visitor operator[](CallPolicies const& policies) const;
};

init requirements init 約束條件

  • ParameterSpecs is an MPL sequence where each element is a model of ParameterSpec. ParameterSpecs 是其每一元素都是 ParameterSpec 模型 的 MPL sequence

  • For every N in [U,V], where [U,V] is the arity range of ParameterSpecs, Class must support these expressions: 對於 [U,V] 裡的每一個 N, 這裡 [U,V]ParameterSpecs元數區間(arity range)Class 必須支持下面的這些表達式:

    Expression 表達式

    Return type 返回類型

    Requirements 約束條件

    Class(a0, …, aN)

    -

    a0aN are tagged arguments. a0aN 必須是帶標籤的參數(tagged arguments)。

template <class CallPolicies> operator[](CallPolicies const&)

Returns a def_visitor equivalent to *this, except that it uses CallPolicies when creating the binding.

返回一個跟 *this 相等的 def_visitor,只是在創建綁定的時候它使用的是 CallPolicies。

Example 例子

#include <boost/parameter/keyword.hpp>
#include <boost/parameter/preprocessor.hpp>
#include <boost/parameter/python.hpp>
#include <boost/python.hpp>
#include <boost/mpl/vector.hpp>

BOOST_PARAMETER_KEYWORD(tag, x)
BOOST_PARAMETER_KEYWORD(tag, y)

struct base
{
template <class ArgumentPack>
base(ArgumentPack const& args)
{
… use args 使用這些參數 … } }; class X : base { public: BOOST_PARAMETER_CONSTRUCTOR(X, (base), tag, (required (x, *)) (optional (y, *)) ) }; BOOST_PYTHON_MODULE(module name)
{
using namespace boost::python;
namespace py = boost::parameter::python;
namespace mpl = boost::mpl;

class_<X>("X", no_init)
.def(
py::init<
mpl::vector<tag::x(int), tag::y*(int)>
>()
);
}

class template call 類模板 call

Defines a __call__ operator, mapped to operator() in C++.

定義了一個 __call__ 操作符,映射到 C++ 裡面的 operator() 操作符。

template <class ParameterSpecs>
struct call : python::def_visitor<call<ParameterSpecs> >
{
template <class Class>
void def(Class& class_);

template <class CallPolicies>
def_visitor operator[](CallPolicies const& policies) const;
};

call requirements call 約束條件

  • ParameterSpecs is an MPL sequence where each element except the first models ParameterSpec. The first element is the result type of c(…). ParameterSpecs 是其除了第一個元素外的每一元素都是 ParameterSpec 模型 的 MPL sequence。 第一個元素是 c(…) 的結果類型(result type)。

  • Class must support these expressions, where c is an instance of Class: Class 必須支持一下這些表達式,其中 cClass 的一個實例:

    Expression 表達式

    Return type 返回類型

    Requirements 約束條件

    c(a0, …, aN)

    Convertible to R 能夠轉化成 R

    a0aN are tagged arguments. a0aN 是帶標籤的參數(tagged arguments)。

    For every N in [U,V], where [U,V] is the arity range of ParameterSpecs.

    對於 [U,V] 裡的每一個 N, 這裡 [U,V]ParameterSpecs元數區間(arity range)

template <class CallPolicies> operator[](CallPolicies const&)

Returns a def_visitor equivalent to *this, except that it uses CallPolicies when creating the binding.

返回一個跟 *this 相等的 def_visitor,只是在創建綁定的時候它使用的是 CallPolicies。

Example 例子

#include <boost/parameter/keyword.hpp>
#include <boost/parameter/preprocessor.hpp>
#include <boost/parameter/python.hpp>
#include <boost/python.hpp>
#include <boost/mpl/vector.hpp>

BOOST_PARAMETER_KEYWORD(tag, x)
BOOST_PARAMETER_KEYWORD(tag, y)

namespace parameter = boost::parameter;

typedef parameter::parameters<
parameter::required<tag::x>
, parameter::optional<tag::y>
> call_parameters;

class X
{
public:
template <class ArgumentPack>
int call_impl(ArgumentPack const& args)
{
… use args 使用這些參數 … } template <class A0> int operator()(A0 const& a0) { return call_impl(call_parameters()(a0)); } template <class A0, class A1> int operator()(A0 const& a0, A1 const& a1) { return call_impl(call_parameters()(a0,a1)); } }; BOOST_PYTHON_MODULE(module name)
{
using namespace boost::python;
namespace py = parameter::python;
namespace mpl = boost::mpl;

class_<X>("X")
.def(
py::call<
mpl::vector<int, tag::x(int), tag::y*(int)>
>()
);
}

class template function 類模板 function

Defines a named parameter enabled member function.

定義一個有名的 parameter式的 成員函數。

template <class Fwd, class ParameterSpecs>
struct function : python::def_visitor<function<Fwd, ParameterSpecs> >
{
template <class Class, class Options>
void def(Class& class_, char const* name, Options const& options);
};

function requirements function 約束條件

  • ParameterSpecs is an MPL sequence where each element except the first models ParameterSpec. The first element is the result type of c.f(…), where f is the member function.

    ParameterSpecs 是其除了第一個元素外的每一個元素都 是 ParameterSpec 模型的一個 MPL sequence。 第一個元素是 c.f(…) 的結果類型(result type),其 中 f 是成員函數。

  • An instance of Fwd must support this expression: 一個 Fwd 實例必須支持以下的表達式:

    Expression 表達式

    Return type 返回類型

    Requirements 約束條件

    fwd(boost::type<R>(), self, a0, …, aN)

    Convertible to R 可以轉化成 R

    self is a reference to the object on which the function should be invoked. a0aN are tagged arguments. self 是指向被調用的成員函數所作用的對象的引用。 a0aN 都是帶標籤的參數(tagged argument)。

    For every N in [U,V], where [U,V] is the arity range of ParameterSpecs.

    對於 [U,V] 裡的每一個 N, 這裡 [U,V]ParameterSpecs元數區間(arity range)

Example 例子

This example exports a member function f(int x, int y = …) to Python. The sequence of ParameterSpec's mpl::vector2<tag::x(int), tag::y*(int)> has an arity range of [2,2], so we only need one forwarding overload.

這個例子導出了一個成員函數 f(int x, int y = …) 到 Python。 ParameterSpecmpl::vector2<tag::x(int), tag::y*(int)> 序列的 元數區間(arity range)[2,2],因此我們只需要一個 轉交重載函數(forwarding overload)。

#include <boost/parameter/keyword.hpp>
#include <boost/parameter/preprocessor.hpp>
#include <boost/parameter/python.hpp>
#include <boost/python.hpp>
#include <boost/mpl/vector.hpp>

BOOST_PARAMETER_KEYWORD(tag, x)
BOOST_PARAMETER_KEYWORD(tag, y)

class X
{
public:
BOOST_PARAMETER_MEMBER_FUNCTION((void), f, tag,
(required (x, *))
(optional (y, *, 1))
)
{
} }; struct f_fwd { template <class A0, class A1> void operator()(boost::type<void>, X& self, A0 const& a0, A1 const& a1) { self.f(a0, a1); } }; BOOST_PYTHON_MODULE(module name)
{
using namespace boost::python;
namespace py = boost::parameter::python;
namespace mpl = boost::mpl;

class_<X>("X")
.def("f",
py::function<
f_fwd
, mpl::vector<void, tag::x(int), tag::y*(int)>
>()
);
}

function template def 函數模板 def

Defines a named parameter enabled free function in the current Python scope.

在當前的 Python 空間(scope)中定義一個有名的 Parameter式 的自由函數。

template <class Fwd, class ParameterSpecs>
void def(char const* name);

def requirements def 約束條件

  • ParameterSpecs is an MPL sequence where each element except the first models ParameterSpec. The first element is the result type of f(…), where f is the function.

    ParameterSpecs 是其除了第一個元素外的每一個元素都是 ParameterSpec 模型的一 個 MPL sequence。第一個元素 是 f(…) 的結果類型,這裡 f 是 一個函數。

  • An instance of Fwd must support this expression:

    一個 Fwd 的實例必須支持這個表達式:

    Expression 表達式

    Return type 返回類型

    Requirements 約束條件

    fwd(boost::type<R>(), a0, …, aN)

    Convertible to R

    可以轉化成 R

    a0aN are tagged arguments.

    a0aN 都是帶標籤的參數(tagged argument)。

    For every N in [U,V], where [U,V] is the arity range of ParameterSpecs.

    對於 [U,V] 中的每一個 N, 其中 [U,V]ParameterSpecs元數區間(arity range)

Example 例子

This example exports a function f(int x, int y = …) to Python. The sequence of ParameterSpec's mpl::vector2<tag::x(int), tag::y*(int)> has an arity range of [2,2], so we only need one forwarding overload.

這個例子導出了一個成員函數 f(int x, int y = …) 到 Python。 ParameterSpecmpl::vector2<tag::x(int), tag::y*(int)> 序列的 元數區間(arity range)[2,2],因此我們只需要一個 轉交重載函數(forwarding overload)。

BOOST_PARAMETER_FUNCTION((void), f, tag,
(required (x, *))
(optional (y, *, 1))
)
{
} struct f_fwd { template <class A0, class A1> void operator()(boost::type<void>, A0 const& a0, A1 const& a1) { f(a0, a1); } }; BOOST_PYTHON_MODULE(…) { def< f_fwd , mpl::vector< void, tag::x(int), tag::y*(int) > >("f"); }

Portability 可移植性

The Boost.Parameter Python binding library requires partial template specialization.

Boost.Parameter Python 綁定庫需要用到 偏特化(partial template specialization) 特性。