make_instance.hpp 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  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. Derived::construct(&instance->storage, (PyObject*)instance, x)->install(raw_result);
  37. // Note the position of the internally-stored Holder,
  38. // for the sake of destruction
  39. Py_SIZE(instance) = offsetof(instance_t, storage);
  40. // Release ownership of the python object
  41. protect.cancel();
  42. }
  43. return raw_result;
  44. }
  45. };
  46. template <class T, class Holder>
  47. struct make_instance
  48. : make_instance_impl<T, Holder, make_instance<T,Holder> >
  49. {
  50. template <class U>
  51. static inline PyTypeObject* get_class_object(U&)
  52. {
  53. return converter::registered<T>::converters.get_class_object();
  54. }
  55. static inline Holder* construct(void* storage, PyObject* instance, reference_wrapper<T const> x)
  56. {
  57. return new (storage) Holder(instance, x);
  58. }
  59. };
  60. }}} // namespace boost::python::object
  61. #endif // MAKE_INSTANCE_DWA200296_HPP