make_instance.hpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  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/none.hpp>
  12. # include <boost/mpl/assert.hpp>
  13. # include <boost/mpl/or.hpp>
  14. # include <boost/type_traits/is_union.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_<is_class<T>, is_union<T> >));
  24. PyTypeObject* type = Derived::get_class_object(x);
  25. if (type == 0)
  26. return python::detail::none();
  27. PyObject* raw_result = type->tp_alloc(
  28. type, objects::additional_instance_size<Holder>::value);
  29. if (raw_result != 0)
  30. {
  31. python::detail::decref_guard protect(raw_result);
  32. instance_t* instance = (instance_t*)raw_result;
  33. // construct the new C++ object and install the pointer
  34. // in the Python object.
  35. Derived::construct(&instance->storage, (PyObject*)instance, x)->install(raw_result);
  36. // Note the position of the internally-stored Holder,
  37. // for the sake of destruction
  38. Py_SIZE(instance) = offsetof(instance_t, storage);
  39. // Release ownership of the python object
  40. protect.cancel();
  41. }
  42. return raw_result;
  43. }
  44. };
  45. template <class T, class Holder>
  46. struct make_instance
  47. : make_instance_impl<T, Holder, make_instance<T,Holder> >
  48. {
  49. template <class U>
  50. static inline PyTypeObject* get_class_object(U&)
  51. {
  52. return converter::registered<T>::converters.get_class_object();
  53. }
  54. static inline Holder* construct(void* storage, PyObject* instance, reference_wrapper<T const> x)
  55. {
  56. return new (storage) Holder(instance, x);
  57. }
  58. };
  59. }}} // namespace boost::python::object
  60. #endif // MAKE_INSTANCE_DWA200296_HPP