object_core.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  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 OBJECT_CORE_DWA2002615_HPP
  6. # define OBJECT_CORE_DWA2002615_HPP
  7. # define BOOST_PYTHON_OBJECT_HAS_IS_NONE // added 2010-03-15 by rwgk
  8. # include <boost/python/detail/prefix.hpp>
  9. # include <boost/type.hpp>
  10. # include <boost/python/call.hpp>
  11. # include <boost/python/handle_fwd.hpp>
  12. # include <boost/python/errors.hpp>
  13. # include <boost/python/refcount.hpp>
  14. # include <boost/python/detail/preprocessor.hpp>
  15. # include <boost/python/tag.hpp>
  16. # include <boost/python/def_visitor.hpp>
  17. # include <boost/python/detail/raw_pyobject.hpp>
  18. # include <boost/python/detail/dependent.hpp>
  19. # include <boost/python/object/forward.hpp>
  20. # include <boost/python/object/add_to_namespace.hpp>
  21. # include <boost/preprocessor/iterate.hpp>
  22. # include <boost/preprocessor/debug/line.hpp>
  23. # include <boost/python/detail/is_xxx.hpp>
  24. # include <boost/python/detail/string_literal.hpp>
  25. # include <boost/python/detail/def_helper_fwd.hpp>
  26. # include <boost/python/detail/type_traits.hpp>
  27. namespace boost { namespace python {
  28. namespace detail
  29. {
  30. class kwds_proxy;
  31. class args_proxy;
  32. }
  33. namespace converter
  34. {
  35. template <class T> struct arg_to_python;
  36. }
  37. // Put this in an inner namespace so that the generalized operators won't take over
  38. namespace api
  39. {
  40. // This file contains the definition of the object class and enough to
  41. // construct/copy it, but not enough to do operations like
  42. // attribute/item access or addition.
  43. template <class Policies> class proxy;
  44. struct const_attribute_policies;
  45. struct attribute_policies;
  46. struct const_objattribute_policies;
  47. struct objattribute_policies;
  48. struct const_item_policies;
  49. struct item_policies;
  50. struct const_slice_policies;
  51. struct slice_policies;
  52. class slice_nil;
  53. typedef proxy<const_attribute_policies> const_object_attribute;
  54. typedef proxy<attribute_policies> object_attribute;
  55. typedef proxy<const_objattribute_policies> const_object_objattribute;
  56. typedef proxy<objattribute_policies> object_objattribute;
  57. typedef proxy<const_item_policies> const_object_item;
  58. typedef proxy<item_policies> object_item;
  59. typedef proxy<const_slice_policies> const_object_slice;
  60. typedef proxy<slice_policies> object_slice;
  61. //
  62. // is_proxy -- proxy type detection
  63. //
  64. BOOST_PYTHON_IS_XXX_DEF(proxy, boost::python::api::proxy, 1)
  65. template <class T> struct object_initializer;
  66. class object;
  67. typedef PyObject* (object::*bool_type)() const;
  68. template <class U>
  69. class object_operators : public def_visitor<U>
  70. {
  71. protected:
  72. typedef object const& object_cref;
  73. public:
  74. // function call
  75. //
  76. object operator()() const;
  77. # define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PYTHON_MAX_ARITY, <boost/python/object_call.hpp>))
  78. # include BOOST_PP_ITERATE()
  79. detail::args_proxy operator* () const;
  80. object operator()(detail::args_proxy const &args) const;
  81. object operator()(detail::args_proxy const &args,
  82. detail::kwds_proxy const &kwds) const;
  83. // truth value testing
  84. //
  85. operator bool_type() const;
  86. bool operator!() const; // needed for vc6
  87. // Attribute access
  88. //
  89. const_object_attribute attr(char const*) const;
  90. object_attribute attr(char const*);
  91. const_object_objattribute attr(object const&) const;
  92. object_objattribute attr(object const&);
  93. // Wrap 'in' operator (aka. __contains__)
  94. template <class T>
  95. object contains(T const& key) const;
  96. // item access
  97. //
  98. const_object_item operator[](object_cref) const;
  99. object_item operator[](object_cref);
  100. template <class T>
  101. const_object_item
  102. operator[](T const& key) const;
  103. template <class T>
  104. object_item
  105. operator[](T const& key);
  106. // slicing
  107. //
  108. const_object_slice slice(object_cref, object_cref) const;
  109. object_slice slice(object_cref, object_cref);
  110. const_object_slice slice(slice_nil, object_cref) const;
  111. object_slice slice(slice_nil, object_cref);
  112. const_object_slice slice(object_cref, slice_nil) const;
  113. object_slice slice(object_cref, slice_nil);
  114. const_object_slice slice(slice_nil, slice_nil) const;
  115. object_slice slice(slice_nil, slice_nil);
  116. template <class T, class V>
  117. const_object_slice
  118. slice(T const& start, V const& end) const;
  119. template <class T, class V>
  120. object_slice
  121. slice(T const& start, V const& end);
  122. private: // def visitation for adding callable objects as class methods
  123. template <class ClassT, class DocStringT>
  124. void visit(ClassT& cl, char const* name, python::detail::def_helper<DocStringT> const& helper) const
  125. {
  126. // It's too late to specify anything other than docstrings if
  127. // the callable object is already wrapped.
  128. BOOST_STATIC_ASSERT(
  129. (detail::is_same<char const*,DocStringT>::value
  130. || detail::is_string_literal<DocStringT const>::value));
  131. objects::add_to_namespace(cl, name, this->derived_visitor(), helper.doc());
  132. }
  133. friend class python::def_visitor_access;
  134. private:
  135. // there is a confirmed CWPro8 codegen bug here. We prevent the
  136. // early destruction of a temporary by binding a named object
  137. // instead.
  138. # if __MWERKS__ < 0x3000 || __MWERKS__ > 0x3003
  139. typedef object const& object_cref2;
  140. # else
  141. typedef object const object_cref2;
  142. # endif
  143. };
  144. // VC6 and VC7 require this base class in order to generate the
  145. // correct copy constructor for object. We can't define it there
  146. // explicitly or it will complain of ambiguity.
  147. struct object_base : object_operators<object>
  148. {
  149. // copy constructor without NULL checking, for efficiency.
  150. inline object_base(object_base const&);
  151. inline object_base(PyObject* ptr);
  152. inline object_base& operator=(object_base const& rhs);
  153. inline ~object_base();
  154. // Underlying object access -- returns a borrowed reference
  155. inline PyObject* ptr() const;
  156. inline bool is_none() const;
  157. private:
  158. PyObject* m_ptr;
  159. };
  160. template <class T, class U>
  161. struct is_derived
  162. : boost::python::detail::is_convertible<
  163. typename detail::remove_reference<T>::type*
  164. , U const*
  165. >
  166. {};
  167. template <class T>
  168. typename objects::unforward_cref<T>::type do_unforward_cref(T const& x)
  169. {
  170. return x;
  171. }
  172. class object;
  173. template <class T>
  174. PyObject* object_base_initializer(T const& x)
  175. {
  176. typedef typename is_derived<
  177. BOOST_DEDUCED_TYPENAME objects::unforward_cref<T>::type
  178. , object
  179. >::type is_obj;
  180. return object_initializer<
  181. BOOST_DEDUCED_TYPENAME unwrap_reference<T>::type
  182. >::get(
  183. x
  184. , is_obj()
  185. );
  186. }
  187. class object : public object_base
  188. {
  189. public:
  190. // default constructor creates a None object
  191. object();
  192. // explicit conversion from any C++ object to Python
  193. template <class T>
  194. explicit object(T const& x)
  195. : object_base(object_base_initializer(x))
  196. {
  197. }
  198. // Throw error_already_set() if the handle is null.
  199. BOOST_PYTHON_DECL explicit object(handle<> const&);
  200. private:
  201. public: // implementation detail -- for internal use only
  202. explicit object(detail::borrowed_reference);
  203. explicit object(detail::new_reference);
  204. explicit object(detail::new_non_null_reference);
  205. };
  206. // Macros for forwarding constructors in classes derived from
  207. // object. Derived classes will usually want these as an
  208. // implementation detail
  209. # define BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(derived, base) \
  210. inline explicit derived(::boost::python::detail::borrowed_reference p) \
  211. : base(p) {} \
  212. inline explicit derived(::boost::python::detail::new_reference p) \
  213. : base(p) {} \
  214. inline explicit derived(::boost::python::detail::new_non_null_reference p) \
  215. : base(p) {}
  216. //
  217. // object_initializer -- get the handle to construct the object with,
  218. // based on whether T is a proxy or derived from object
  219. //
  220. template <bool is_proxy = false, bool is_object_manager = false>
  221. struct object_initializer_impl
  222. {
  223. static PyObject*
  224. get(object const& x, detail::true_)
  225. {
  226. return python::incref(x.ptr());
  227. }
  228. template <class T>
  229. static PyObject*
  230. get(T const& x, detail::false_)
  231. {
  232. return python::incref(converter::arg_to_python<T>(x).get());
  233. }
  234. };
  235. template <>
  236. struct object_initializer_impl<true, false>
  237. {
  238. template <class Policies>
  239. static PyObject*
  240. get(proxy<Policies> const& x, detail::false_)
  241. {
  242. return python::incref(x.operator object().ptr());
  243. }
  244. };
  245. template <>
  246. struct object_initializer_impl<false, true>
  247. {
  248. template <class T, class U>
  249. static PyObject*
  250. get(T const& x, U)
  251. {
  252. return python::incref(get_managed_object(x, boost::python::tag));
  253. }
  254. };
  255. template <>
  256. struct object_initializer_impl<true, true>
  257. {}; // empty implementation should cause an error
  258. template <class T>
  259. struct object_initializer : object_initializer_impl<
  260. is_proxy<T>::value
  261. , converter::is_object_manager<T>::value
  262. >
  263. {};
  264. }
  265. using api::object;
  266. template <class T> struct extract;
  267. //
  268. // implementation
  269. //
  270. namespace detail
  271. {
  272. class call_proxy
  273. {
  274. public:
  275. call_proxy(object target) : m_target(target) {}
  276. operator object() const { return m_target;}
  277. private:
  278. object m_target;
  279. };
  280. class kwds_proxy : public call_proxy
  281. {
  282. public:
  283. kwds_proxy(object o = object()) : call_proxy(o) {}
  284. };
  285. class args_proxy : public call_proxy
  286. {
  287. public:
  288. args_proxy(object o) : call_proxy(o) {}
  289. kwds_proxy operator* () const { return kwds_proxy(*this);}
  290. };
  291. }
  292. template <typename U>
  293. detail::args_proxy api::object_operators<U>::operator* () const
  294. {
  295. object_cref2 x = *static_cast<U const*>(this);
  296. return boost::python::detail::args_proxy(x);
  297. }
  298. template <typename U>
  299. object api::object_operators<U>::operator()(detail::args_proxy const &args) const
  300. {
  301. U const& self = *static_cast<U const*>(this);
  302. PyObject *result = PyObject_Call(get_managed_object(self, boost::python::tag),
  303. args.operator object().ptr(),
  304. 0);
  305. return object(boost::python::detail::new_reference(result));
  306. }
  307. template <typename U>
  308. object api::object_operators<U>::operator()(detail::args_proxy const &args,
  309. detail::kwds_proxy const &kwds) const
  310. {
  311. U const& self = *static_cast<U const*>(this);
  312. PyObject *result = PyObject_Call(get_managed_object(self, boost::python::tag),
  313. args.operator object().ptr(),
  314. kwds.operator object().ptr());
  315. return object(boost::python::detail::new_reference(result));
  316. }
  317. template <typename U>
  318. template <class T>
  319. object api::object_operators<U>::contains(T const& key) const
  320. {
  321. return this->attr("__contains__")(object(key));
  322. }
  323. inline object::object()
  324. : object_base(python::incref(Py_None))
  325. {}
  326. // copy constructor without NULL checking, for efficiency
  327. inline api::object_base::object_base(object_base const& rhs)
  328. : m_ptr(python::incref(rhs.m_ptr))
  329. {}
  330. inline api::object_base::object_base(PyObject* p)
  331. : m_ptr(p)
  332. {}
  333. inline api::object_base& api::object_base::operator=(api::object_base const& rhs)
  334. {
  335. Py_INCREF(rhs.m_ptr);
  336. Py_DECREF(this->m_ptr);
  337. this->m_ptr = rhs.m_ptr;
  338. return *this;
  339. }
  340. inline api::object_base::~object_base()
  341. {
  342. assert( Py_REFCNT(m_ptr) > 0 );
  343. Py_DECREF(m_ptr);
  344. }
  345. inline object::object(detail::borrowed_reference p)
  346. : object_base(python::incref((PyObject*)p))
  347. {}
  348. inline object::object(detail::new_reference p)
  349. : object_base(expect_non_null((PyObject*)p))
  350. {}
  351. inline object::object(detail::new_non_null_reference p)
  352. : object_base((PyObject*)p)
  353. {}
  354. inline PyObject* api::object_base::ptr() const
  355. {
  356. return m_ptr;
  357. }
  358. inline bool api::object_base::is_none() const
  359. {
  360. return (m_ptr == Py_None);
  361. }
  362. //
  363. // Converter specialization implementations
  364. //
  365. namespace converter
  366. {
  367. template <class T> struct object_manager_traits;
  368. template <>
  369. struct object_manager_traits<object>
  370. {
  371. BOOST_STATIC_CONSTANT(bool, is_specialized = true);
  372. static bool check(PyObject*) { return true; }
  373. static python::detail::new_non_null_reference adopt(PyObject* x)
  374. {
  375. return python::detail::new_non_null_reference(x);
  376. }
  377. #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
  378. static PyTypeObject const *get_pytype() {return 0;}
  379. #endif
  380. };
  381. }
  382. inline PyObject* get_managed_object(object const& x, tag_t)
  383. {
  384. return x.ptr();
  385. }
  386. }} // namespace boost::python
  387. # include <boost/python/slice_nil.hpp>
  388. #endif // OBJECT_CORE_DWA2002615_HPP