back_reference.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // Copyright David Abrahams 2002.
  2. // Distributed under the Boost Software License, Version 1.0. (See
  3. // accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. #include <boost/python/class.hpp>
  6. #include <boost/python/module.hpp>
  7. #include <boost/python/def.hpp>
  8. #include <boost/python/has_back_reference.hpp>
  9. #include <boost/python/back_reference.hpp>
  10. #include <boost/ref.hpp>
  11. #include <boost/utility.hpp>
  12. #include <memory>
  13. #define BOOST_ENABLE_ASSERT_HANDLER
  14. #include <boost/assert.hpp>
  15. #include <boost/python/copy_const_reference.hpp>
  16. #include <boost/python/return_value_policy.hpp>
  17. #include <boost/mpl/bool.hpp>
  18. // This test shows that a class can be wrapped "as itself" but also
  19. // acquire a back-reference iff has_back_reference<> is appropriately
  20. // specialized.
  21. using namespace boost::python;
  22. struct X
  23. {
  24. explicit X(int x) : x(x), magic(7654321) { ++counter; }
  25. X(X const& rhs) : x(rhs.x), magic(7654321) { ++counter; }
  26. virtual ~X() { BOOST_ASSERT(magic == 7654321); magic = 6666666; x = 9999; --counter; }
  27. void set(int _x) { BOOST_ASSERT(magic == 7654321); this->x = _x; }
  28. int value() const { BOOST_ASSERT(magic == 7654321); return x; }
  29. static int count() { return counter; }
  30. private:
  31. void operator=(X const&);
  32. private:
  33. int x;
  34. long magic;
  35. static int counter;
  36. };
  37. int X::counter;
  38. struct Y : X
  39. {
  40. Y(PyObject* self, int x) : X(x), self(self) {}
  41. Y(PyObject* self, Y const& rhs) : X(rhs), self(self) {}
  42. private:
  43. Y(Y const&);
  44. PyObject* self;
  45. };
  46. struct Z : X
  47. {
  48. Z(PyObject* self, int x) : X(x), self(self) {}
  49. Z(PyObject* self, Z const& rhs) : X(rhs), self(self) {}
  50. private:
  51. Z(Z const&);
  52. PyObject* self;
  53. };
  54. Y const& copy_Y(Y const& y) { return y; }
  55. Z const& copy_Z(Z const& z) { return z; }
  56. namespace boost { namespace python
  57. {
  58. template <>
  59. struct has_back_reference<Y>
  60. : mpl::true_
  61. {
  62. };
  63. template <>
  64. struct has_back_reference<Z>
  65. : mpl::true_
  66. {
  67. };
  68. }}
  69. // prove that back_references get initialized with the right PyObject*
  70. object y_identity(back_reference<Y const&> y)
  71. {
  72. return y.source();
  73. }
  74. // prove that back_references contain the right value
  75. bool y_equality(back_reference<Y const&> y1, Y const& y2)
  76. {
  77. return &y1.get() == &y2;
  78. }
  79. BOOST_PYTHON_MODULE(back_reference_ext)
  80. {
  81. def("copy_Y", copy_Y, return_value_policy<copy_const_reference>());
  82. def("copy_Z", copy_Z, return_value_policy<copy_const_reference>());
  83. def("x_instances", &X::count);
  84. class_<Y>("Y", init<int>())
  85. .def("value", &Y::value)
  86. .def("set", &Y::set)
  87. ;
  88. class_<Z,std::auto_ptr<Z> >("Z", init<int>())
  89. .def("value", &Z::value)
  90. .def("set", &Z::set)
  91. ;
  92. def("y_identity", y_identity);
  93. def("y_equality", y_equality);
  94. }
  95. #include "module_tail.cpp"