boost/python/pytype_function.hpp

はじめに

Python のシグニチャをサポートするには、変換器は関連する PyTypeObject へのポインタを返す get_pytype 関数を提供しなければならない。例として ResultConverterto_python_converter を見るとよい。このヘッダファイルのクラスは get_pytype の実装に使用することを想定している。修飾無しの引数型とともに使用する T に対するテンプレートの _direct1もある(これらはモジュールを読み込んだときに変換レジストリ内にあると考えてしかるべきものである)。

クラス

wrap_pytype クラス

template<PyTypeObject const *pytype>
class wrap_pytype

このテンプレートは、テンプレート引数を返す静的メンバ get_pytype を生成する。

wrap_pytype クラスの概要

namespace boost { namespace python { namespace converter{

    template < PyTypeObject const *pytype >
    class wrap_pytype
    {
      public:
          static PyTypeObject const *get_pytype(){return pytype; }
    };

}}}

registered_pytype クラス

template<class T>
class registered_pytype

このテンプレートは、class_ で Python へエクスポートする型(修飾子があってもよい)のテンプレート引数とともに使用すべきである。生成された静的メンバ get_pytype は対応する Python の型を返す。

registered_pytype クラスの概要

namespace boost { namespace python { namespace converter{

    template < class T >
    class registered_pytype
    {
      public:
          static PyTypeObject const *get_pytype();
    };

}}}

expected_from_python_type クラス

template<class T>
class expected_from_python_type

このテンプレートは、型 T について登録済みの from_python 変換器を問い合わせし合致した Python 型を返す静的メンバ get_pytype を生成する。

expected_from_python_type クラスの概要

namespace boost { namespace python { namespace converter{

    template < class T >
    class expected_from_python_type
    {
      public:
          static PyTypeObject const *get_pytype();
    };

}}}

to_python_target_type クラス

template<class T>
class to_python_target_type

このテンプレートは、T から変換可能な Python の型を返す静的メンバ get_pytype を生成する。

to_python_target_type クラスの概要

namespace boost { namespace python { namespace converter{

    template < class T >
    class to_python_target_type
    {
      public:
          static PyTypeObject const *get_pytype();
    };

}}}

以下の例では、Python のドキュメントにある標準的な noddy モジュール例を実装したとして、関連する宣言を noddy.h に置いたものと仮定する。noddy_NoddyObject は極限なまでに単純な拡張型であるので、この例は少しばかりわざとらしい。すべての情報がその戻り値の型に含まれる関数をラップしている。

C++ のモジュール定義
#include <boost/python/reference.hpp>
#include <boost/python/module.hpp>
#include "noddy.h"

struct tag {};
tag make_tag() { return tag(); }

using namespace boost::python;

struct tag_to_noddy
#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES // Python のシグニチャがサポートされない場合は不要なオーバーヘッドが発生
: wrap_pytype<&noddy_NoddyType> // wrap_pytype から get_pytype を継承する
#endif
{
    static PyObject* convert(tag const& x)
    {
        return PyObject_New(noddy_NoddyObject, &noddy_NoddyType);
    }
};

BOOST_PYTHON_MODULE(to_python_converter)
{
    def("make_tag", make_tag);
    to_python_converter<tag, tag_to_noddy
#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES // Python のシグニチャがサポートされない場合は不正
          , true
#endif
          >(); // tag_to_noddy がメンバ get_pytype を持つので「真」
}

以下の例は、テンプレート expected_from_python_type および to_python_target_type を使用して Python との双方向変換器を登録している。

#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/extract.hpp>
#include <boost/python/to_python_converter.hpp>
#include <boost/python/class.hpp>

using namespace boost::python;

struct A
{
};

struct B
{
  A a;
  B(const A& a_):a(a_){}
};

// A から Python の整数への変換器
struct BToPython
#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES // Python のシグニチャがサポートされていない場合は不要なオーバーヘッドが発生
   : converter::to_python_target_type<A>  // get_pytype を継承する
#endif
{
  static PyObject* convert(const B& b)
  {
    return incref(object(b.a).ptr());
  }
};

// Python の整数から A への変換
struct BFromPython
{
  BFromPython()
  {
    boost::python::converter::registry::push_back
        ( &convertible
        , &construct
        , type_id< B >()
#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES // Python のシグニチャがサポートされていない場合は不正
        , &converter::expected_from_python_type<A>::get_pytype// A へ変換可能なものは B へ変換可能
#endif
        );
  }

  static void* convertible(PyObject* obj_ptr)
  {
      extract<const A&> ex(obj_ptr);
      if (!ex.check()) return 0;
      return obj_ptr;
  }

  static void construct(
      PyObject* obj_ptr,
      converter::rvalue_from_python_stage1_data* data)
  {
    void* storage = (
        (converter::rvalue_from_python_storage< B >*)data)-> storage.bytes;

    extract<const A&> ex(obj_ptr);
    new (storage) B(ex());
    data->convertible = storage;
  }
};


B func(const B& b) { return b ; }

BOOST_PYTHON_MODULE(pytype_function_ext)
{
  to_python_converter< B , BtoPython
#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES // Python のシグニチャがサポートされていない場合は不正
             ,true
#endif
             >(); // get_pytype を持つ
  BFromPython();

  class_<A>("A") ;

  def("func", &func);

}

>>> from pytype_function_ext import *
>>> print func.__doc__
func( (A)arg1) -> A :
    C++ signature:
         struct B func(struct B)
1

訳注 expected_from_python_type_directregistered_pytype_directto_python_target_type_direct の 3 つ。