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