make_instance.hpp 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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. #ifndef MAKE_INSTANCE_DWA200296_HPP
  6. # define MAKE_INSTANCE_DWA200296_HPP
  7. # include <boost/python/detail/prefix.hpp>
  8. # include <boost/python/object/instance.hpp>
  9. # include <boost/python/converter/registered.hpp>
  10. # include <boost/python/detail/decref_guard.hpp>
  11. # include <boost/python/detail/type_traits.hpp>
  12. # include <boost/python/detail/none.hpp>
  13. # include <boost/mpl/assert.hpp>
  14. # include <boost/mpl/or.hpp>
  15. namespace boost { namespace python { namespace objects {
  16. template <class T, class Holder, class Derived>
  17. struct make_instance_impl
  18. {
  19. typedef objects::instance<Holder> instance_t;
  20. template <class Arg>
  21. static inline PyObject* execute(Arg& x)
  22. {
  23. BOOST_MPL_ASSERT((mpl::or_<boost::python::detail::is_class<T>,
  24. boost::python::detail::is_union<T> >));
  25. PyTypeObject* type = Derived::get_class_object(x);
  26. if (type == 0)
  27. return python::detail::none();
  28. PyObject* raw_result = type->tp_alloc(
  29. type, objects::additional_instance_size<Holder>::value);
  30. if (raw_result != 0)
  31. {
  32. python::detail::decref_guard protect(raw_result);
  33. instance_t* instance = (instance_t*)raw_result;
  34. // construct the new C++ object and install the pointer
  35. // in the Python object.
  36. Holder *holder =Derived::construct(instance->storage.bytes, (PyObject*)instance, x);
  37. holder->install(raw_result);
  38. // Note the position of the internally-stored Holder,
  39. // for the sake of destruction
  40. const size_t offset = reinterpret_cast<size_t>(holder) -
  41. reinterpret_cast<size_t>(instance->storage.bytes) + offsetof(instance_t, storage);
  42. Py_SET_SIZE(instance, offset);
  43. // Release ownership of the python object
  44. protect.cancel();
  45. }
  46. return raw_result;
  47. }
  48. };
  49. template <class T, class Holder>
  50. struct make_instance
  51. : make_instance_impl<T, Holder, make_instance<T,Holder> >
  52. {
  53. template <class U>
  54. static inline PyTypeObject* get_class_object(U&)
  55. {
  56. return converter::registered<T>::converters.get_class_object();
  57. }
  58. static inline Holder* construct(void* storage, PyObject* instance, reference_wrapper<T const> x)
  59. {
  60. size_t allocated = objects::additional_instance_size<Holder>::value;
  61. void* aligned_storage = ::boost::alignment::align(boost::python::detail::alignment_of<Holder>::value,
  62. sizeof(Holder), storage, allocated);
  63. return new (aligned_storage) Holder(instance, x);
  64. }
  65. };
  66. }}} // namespace boost::python::object
  67. #endif // MAKE_INSTANCE_DWA200296_HPP