pytype_function.qbk 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. [section boost/python/pytype_function.hpp]
  2. [section Introduction]
  3. To 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`]
  6. This template generates a static `get_pytype` member returning the template parameter.
  7. ``
  8. namespace boost { namespace python { namespace converter{
  9. template < PyTypeObject const *pytype >
  10. class wrap_pytype
  11. {
  12. public:
  13. static PyTypeObject const *get_pytype(){return pytype; }
  14. };
  15. }}}
  16. ``
  17. [endsect]
  18. [section Class `registered_pytype`]
  19. This 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.
  20. ``
  21. namespace boost { namespace python { namespace converter{
  22. template < class T >
  23. class registered_pytype
  24. {
  25. public:
  26. static PyTypeObject const *get_pytype();
  27. };
  28. }}}
  29. ``
  30. [endsect]
  31. [section Class `expected_from_python_type`]
  32. This template generates a static `get_pytype` member which inspects the registered `from_python` converters for the type `T` and returns a matching python type.
  33. ``
  34. namespace boost { namespace python { namespace converter{
  35. template < class T >
  36. class expected_from_python_type
  37. {
  38. public:
  39. static PyTypeObject const *get_pytype();
  40. };
  41. }}}
  42. ``
  43. [endsect]
  44. [section Class `to_python_target_type`]
  45. This template generates a static `get_pytype` member returning the python type to which `T` can be converted.
  46. ``
  47. namespace boost { namespace python { namespace converter{
  48. template < class T >
  49. class to_python_target_type
  50. {
  51. public:
  52. static PyTypeObject const *get_pytype();
  53. };
  54. }}}
  55. ``
  56. [endsect]
  57. [section Example]
  58. This 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.
  59. C++ module definition:
  60. ``
  61. #include <boost/python/reference.hpp>
  62. #include <boost/python/module.hpp>
  63. #include "noddy.h"
  64. struct tag {};
  65. tag make_tag() { return tag(); }
  66. using namespace boost::python;
  67. struct tag_to_noddy
  68. #if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //unnecessary overhead if py signatures are not supported
  69. : wrap_pytype<&noddy_NoddyType> //inherits get_pytype from wrap_pytype
  70. #endif
  71. {
  72. static PyObject* convert(tag const& x)
  73. {
  74. return PyObject_New(noddy_NoddyObject, &noddy_NoddyType);
  75. }
  76. };
  77. BOOST_PYTHON_MODULE(to_python_converter)
  78. {
  79. def("make_tag", make_tag);
  80. to_python_converter<tag, tag_to_noddy
  81. #if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
  82. , true
  83. #endif
  84. >(); //"true" because tag_to_noddy has member get_pytype
  85. }
  86. ``
  87. The following example registers to and from python converters using the templates expected_from_python_type and to_pyhton_target_type.
  88. ``
  89. #include <boost/python/module.hpp>
  90. #include <boost/python/def.hpp>
  91. #include <boost/python/extract.hpp>
  92. #include <boost/python/to_python_converter.hpp>
  93. #include <boost/python/class.hpp>
  94. using namespace boost::python;
  95. struct A
  96. {
  97. };
  98. struct B
  99. {
  100. A a;
  101. B(const A& a_):a(a_){}
  102. };
  103. // Converter from A to python int
  104. struct BToPython
  105. #if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //unnecessary overhead if py signatures are not supported
  106. : converter::to_python_target_type<A> //inherits get_pytype
  107. #endif
  108. {
  109. static PyObject* convert(const B& b)
  110. {
  111. return incref(object(b.a).ptr());
  112. }
  113. };
  114. // Conversion from python int to A
  115. struct BFromPython
  116. {
  117. BFromPython()
  118. {
  119. boost::python::converter::registry::push_back
  120. ( &convertible
  121. , &construct
  122. , type_id< B >()
  123. #if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
  124. , &converter::expected_from_python_type<A>::get_pytype//convertible to A can be converted to B
  125. #endif
  126. );
  127. }
  128. static void* convertible(PyObject* obj_ptr)
  129. {
  130. extract<const A&> ex(obj_ptr);
  131. if (!ex.check()) return 0;
  132. return obj_ptr;
  133. }
  134. static void construct(
  135. PyObject* obj_ptr,
  136. converter::rvalue_from_python_stage1_data* data)
  137. {
  138. void* storage = (
  139. (converter::rvalue_from_python_storage< B >*)data)-> storage.bytes;
  140. extract<const A&> ex(obj_ptr);
  141. new (storage) B(ex());
  142. data->convertible = storage;
  143. }
  144. };
  145. B func(const B& b) { return b ; }
  146. BOOST_PYTHON_MODULE(pytype_function_ext)
  147. {
  148. to_python_converter< B , BToPython
  149. #if defined BOOST_PYTHON_SUPPORTS_PY_SIGNATURES //invalid if py signatures are not supported
  150. ,true
  151. #endif
  152. >(); //has get_pytype
  153. BFromPython();
  154. class_<A>("A") ;
  155. def("func", &func);
  156. }
  157. >>> from pytype_function_ext import *
  158. >>> print func.__doc__
  159. func( (A)arg1) -> A :
  160. C++ signature:
  161. struct B func(struct B)
  162. ``
  163. [endsect]
  164. [endsect]