• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[section boost/python/pytype_function.hpp]
2[section Introduction]
3To support Pythonic signatures the converters should supply a `get_pytype` function returning a pointer to the associated `PyTypeObject`. See for example [link concepts.resultconverter `ResultConverter`] or [link to_from_python_type_conversion.boost_python_to_python_converter.class_template_to_python_convert.class_template_to_python_convert `to_python_converter`]. The classes in this header file are meant to be used when implmenting `get_pytype`. There are also `_direct` versions of the templates of `class T` which should be used with undecorated type parameter, expected to be in the conversion registry when the module loads.
4[endsect]
5[section Class `wrap_pytype`]
6This template generates a static `get_pytype` member returning the template parameter.
7``
8namespace boost { namespace python { namespace converter{
9
10    template < PyTypeObject const *pytype >
11    class wrap_pytype
12    {
13      public:
14          static PyTypeObject const *get_pytype(){return pytype; }
15    };
16
17}}}
18``
19[endsect]
20[section Class `registered_pytype`]
21This template should be used with template parameters which are (possibly decorated) types exported to python using [link high_level_components.boost_python_class_hpp.class_template_class_t_bases_hel `class_`]. The generated a static `get_pytype` member returns the corresponding python type.
22``
23namespace boost { namespace python { namespace converter{
24
25    template < class T >
26    class registered_pytype
27    {
28      public:
29          static PyTypeObject const *get_pytype();
30    };
31
32}}}
33``
34[endsect]
35[section Class `expected_from_python_type`]
36This template generates a static `get_pytype` member which inspects the registered `from_python` converters for the type `T` and returns a matching python type.
37``
38namespace boost { namespace python { namespace converter{
39
40    template < class T >
41    class expected_from_python_type
42    {
43      public:
44          static PyTypeObject const *get_pytype();
45    };
46
47}}}
48``
49[endsect]
50[section Class `to_python_target_type`]
51This template generates a static `get_pytype` member returning the python type to which `T` can be converted.
52``
53namespace boost { namespace python { namespace converter{
54
55    template < class T >
56    class to_python_target_type
57    {
58      public:
59          static PyTypeObject const *get_pytype();
60    };
61
62}}}
63``
64[endsect]
65[section Example]
66This example presumes that someone has implemented the standard noddy example module from the Python documentation, and placed the corresponding declarations in "noddy.h". Because `noddy_NoddyObject` is the ultimate trivial extension type, the example is a bit contrived: it wraps a function for which all information is contained in the type of its return value.
67
68C++ module definition:
69``
70#include <boost/python/reference.hpp>
71#include <boost/python/module.hpp>
72#include "noddy.h"
73
74struct tag {};
75tag make_tag() { return tag(); }
76
77using namespace boost::python;
78
79struct tag_to_noddy
80#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //unnecessary overhead if py signatures are not supported
81: wrap_pytype<&noddy_NoddyType> //inherits get_pytype from wrap_pytype
82#endif
83{
84    static PyObject* convert(tag const& x)
85    {
86        return PyObject_New(noddy_NoddyObject, &noddy_NoddyType);
87    }
88};
89
90BOOST_PYTHON_MODULE(to_python_converter)
91{
92    def("make_tag", make_tag);
93    to_python_converter<tag, tag_to_noddy
94#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
95          , true
96#endif
97          >(); //"true" because tag_to_noddy has member get_pytype
98}
99``
100The following example registers to and from python converters using the templates expected_from_python_type and to_pyhton_target_type.
101``
102#include <boost/python/module.hpp>
103#include <boost/python/def.hpp>
104#include <boost/python/extract.hpp>
105#include <boost/python/to_python_converter.hpp>
106#include <boost/python/class.hpp>
107
108using namespace boost::python;
109
110struct A
111{
112};
113
114struct B
115{
116  A a;
117  B(const A& a_):a(a_){}
118};
119
120// Converter from A to python int
121struct BToPython
122#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //unnecessary overhead if py signatures are not supported
123   : converter::to_python_target_type<A>  //inherits get_pytype
124#endif
125{
126  static PyObject* convert(const B& b)
127  {
128    return incref(object(b.a).ptr());
129  }
130};
131
132// Conversion from python int to A
133struct BFromPython
134{
135  BFromPython()
136  {
137    boost::python::converter::registry::push_back
138        ( &convertible
139        , &construct
140        , type_id< B >()
141#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
142        , &converter::expected_from_python_type<A>::get_pytype//convertible to A can be converted to B
143#endif
144        );
145  }
146
147  static void* convertible(PyObject* obj_ptr)
148  {
149      extract<const A&> ex(obj_ptr);
150      if (!ex.check()) return 0;
151      return obj_ptr;
152  }
153
154  static void construct(
155      PyObject* obj_ptr,
156      converter::rvalue_from_python_stage1_data* data)
157  {
158    void* storage = (
159        (converter::rvalue_from_python_storage< B >*)data)-> storage.bytes;
160
161    extract<const A&> ex(obj_ptr);
162    new (storage) B(ex());
163    data->convertible = storage;
164  }
165};
166
167
168B func(const B& b) { return b ; }
169
170BOOST_PYTHON_MODULE(pytype_function_ext)
171{
172  to_python_converter< B , BToPython
173#if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
174             ,true
175#endif
176             >(); //has get_pytype
177  BFromPython();
178
179  class_<A>("A") ;
180
181  def("func", &func);
182
183}
184
185
186
187>>> from pytype_function_ext import *
188>>> print func.__doc__
189func( (A)arg1) -> A :
190    C++ signature:
191         struct B func(struct B)
192``
193[endsect]
194[endsect]
195