has_back_reference.qbk 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. [section boost/python/has_back_reference.hpp]
  2. [section Introduction]
  3. <boost/python/has_back_reference.hpp> defines the predicate metafunction `has_back_reference<>`, which can be specialized by the user to indicate that a wrapped class instance holds a `PyObject*` corresponding to a Python object.
  4. [endsect]
  5. [section Class template `has_back_reference`]
  6. A unary metafunction whose value is true iff its argument is a `pointer_wrapper<>`.
  7. ``
  8. namespace boost { namespace python
  9. {
  10. template<class WrappedClass> class has_back_reference
  11. {
  12. typedef mpl::false_ type;
  13. };
  14. }}
  15. ``
  16. A metafunction that is inspected by Boost.Python to determine how wrapped classes can be constructed.
  17. `type::value` is an integral constant convertible to bool of unspecified type.
  18. Specializations may substitute a true-valued integral constant wrapper for type iff for each invocation of `class_<WrappedClass>::def(init< type-sequence...>())` and the implicitly wrapped copy constructor (unless it is noncopyable), there exists a corresponding constructor `WrappedClass::WrappedClass(PyObject*, type-sequence...)`. If such a specialization exists, the WrappedClass constructors will be called with a "back reference" pointer to the corresponding Python object whenever they are invoked from Python. The easiest way to provide this nested type is to derive the specialization from `mpl::true_`.
  19. [endsect]
  20. [section Examples]
  21. In C++:
  22. ``
  23. #include <boost/python/class.hpp>
  24. #include <boost/python/module.hpp>
  25. #include <boost/python/has_back_reference.hpp>
  26. #include <boost/python/handle.hpp>
  27. #include <boost/shared_ptr.hpp>
  28. using namespace boost::python;
  29. using boost::shared_ptr;
  30. struct X
  31. {
  32. X(PyObject* self) : m_self(self), m_x(0) {}
  33. X(PyObject* self, int x) : m_self(self), m_x(x) {}
  34. X(PyObject* self, X const& other) : m_self(self), m_x(other.m_x) {}
  35. handle<> self() { return handle<>(borrowed(m_self)); }
  36. int get() { return m_x; }
  37. void set(int x) { m_x = x; }
  38. PyObject* m_self;
  39. int m_x;
  40. };
  41. // specialize has_back_reference for X
  42. namespace boost { namespace python
  43. {
  44. template <>
  45. struct has_back_reference<X>
  46. : mpl::true_
  47. {};
  48. }}
  49. struct Y
  50. {
  51. Y() : m_x(0) {}
  52. Y(int x) : m_x(x) {}
  53. int get() { return m_x; }
  54. void set(int x) { m_x = x; }
  55. int m_x;
  56. };
  57. shared_ptr<Y>
  58. Y_self(shared_ptr<Y> self) { return self; }
  59. BOOST_PYTHON_MODULE(back_references)
  60. {
  61. class_<X>("X")
  62. .def(init<int>())
  63. .def("self", &X::self)
  64. .def("get", &X::get)
  65. .def("set", &X::set)
  66. ;
  67. class_<Y, shared_ptr<Y> >("Y")
  68. .def(init<int>())
  69. .def("get", &Y::get)
  70. .def("set", &Y::set)
  71. .def("self", Y_self)
  72. ;
  73. }
  74. ``
  75. The following Python session illustrates that x.self() returns the same Python object on which it is invoked, while y.self() must create a new Python object which refers to the same Y instance.
  76. In Python:
  77. ``
  78. >>> from back_references import *
  79. >>> x = X(1)
  80. >>> x2 = x.self()
  81. >>> x2 is x
  82. 1
  83. >>> (x.get(), x2.get())
  84. (1, 1)
  85. >>> x.set(10)
  86. >>> (x.get(), x2.get())
  87. (10, 10)
  88. >>>
  89. >>>
  90. >>> y = Y(2)
  91. >>> y2 = y.self()
  92. >>> y2 is y
  93. 0
  94. >>> (y.get(), y2.get())
  95. (2, 2)
  96. >>> y.set(20)
  97. >>> (y.get(), y2.get())
  98. (20, 20)
  99. ``
  100. [endsect]
  101. [endsect]