object_core.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583
  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/type_traits/is_same.hpp>
  27. # include <boost/type_traits/is_convertible.hpp>
  28. # include <boost/type_traits/remove_reference.hpp>
  29. # if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
  30. # include <boost/type_traits/add_pointer.hpp>
  31. # endif
  32. # include <boost/mpl/if.hpp>
  33. namespace boost { namespace python {
  34. namespace detail
  35. {
  36. class kwds_proxy;
  37. class args_proxy;
  38. }
  39. namespace converter
  40. {
  41. template <class T> struct arg_to_python;
  42. }
  43. // Put this in an inner namespace so that the generalized operators won't take over
  44. namespace api
  45. {
  46. // This file contains the definition of the object class and enough to
  47. // construct/copy it, but not enough to do operations like
  48. // attribute/item access or addition.
  49. template <class Policies> class proxy;
  50. struct const_attribute_policies;
  51. struct attribute_policies;
  52. struct const_objattribute_policies;
  53. struct objattribute_policies;
  54. struct const_item_policies;
  55. struct item_policies;
  56. struct const_slice_policies;
  57. struct slice_policies;
  58. class slice_nil;
  59. typedef proxy<const_attribute_policies> const_object_attribute;
  60. typedef proxy<attribute_policies> object_attribute;
  61. typedef proxy<const_objattribute_policies> const_object_objattribute;
  62. typedef proxy<objattribute_policies> object_objattribute;
  63. typedef proxy<const_item_policies> const_object_item;
  64. typedef proxy<item_policies> object_item;
  65. typedef proxy<const_slice_policies> const_object_slice;
  66. typedef proxy<slice_policies> object_slice;
  67. //
  68. // is_proxy -- proxy type detection
  69. //
  70. BOOST_PYTHON_IS_XXX_DEF(proxy, boost::python::api::proxy, 1)
  71. template <class T> struct object_initializer;
  72. class object;
  73. typedef PyObject* (object::*bool_type)() const;
  74. template <class U>
  75. class object_operators : public def_visitor<U>
  76. {
  77. protected:
  78. # if !defined(BOOST_MSVC) || BOOST_MSVC >= 1300
  79. typedef object const& object_cref;
  80. # else
  81. typedef object object_cref;
  82. # endif
  83. public:
  84. // function call
  85. //
  86. object operator()() const;
  87. # define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PYTHON_MAX_ARITY, <boost/python/object_call.hpp>))
  88. # include BOOST_PP_ITERATE()
  89. detail::args_proxy operator* () const;
  90. object operator()(detail::args_proxy const &args) const;
  91. object operator()(detail::args_proxy const &args,
  92. detail::kwds_proxy const &kwds) const;
  93. // truth value testing
  94. //
  95. operator bool_type() const;
  96. bool operator!() const; // needed for vc6
  97. // Attribute access
  98. //
  99. const_object_attribute attr(char const*) const;
  100. object_attribute attr(char const*);
  101. const_object_objattribute attr(object const&) const;
  102. object_objattribute attr(object const&);
  103. // Wrap 'in' operator (aka. __contains__)
  104. template <class T>
  105. object contains(T const& key) const;
  106. // item access
  107. //
  108. const_object_item operator[](object_cref) const;
  109. object_item operator[](object_cref);
  110. template <class T>
  111. const_object_item
  112. operator[](T const& key) const
  113. # if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
  114. ;
  115. # else
  116. {
  117. return (*this)[object(key)];
  118. }
  119. # endif
  120. template <class T>
  121. object_item
  122. operator[](T const& key)
  123. # if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
  124. ;
  125. # else
  126. {
  127. return (*this)[object(key)];
  128. }
  129. # endif
  130. // slicing
  131. //
  132. const_object_slice slice(object_cref, object_cref) const;
  133. object_slice slice(object_cref, object_cref);
  134. const_object_slice slice(slice_nil, object_cref) const;
  135. object_slice slice(slice_nil, object_cref);
  136. const_object_slice slice(object_cref, slice_nil) const;
  137. object_slice slice(object_cref, slice_nil);
  138. const_object_slice slice(slice_nil, slice_nil) const;
  139. object_slice slice(slice_nil, slice_nil);
  140. template <class T, class V>
  141. const_object_slice
  142. slice(T const& start, V const& end) const
  143. # if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
  144. ;
  145. # else
  146. {
  147. return this->slice(
  148. slice_bound<T>::type(start)
  149. , slice_bound<V>::type(end));
  150. }
  151. # endif
  152. template <class T, class V>
  153. object_slice
  154. slice(T const& start, V const& end)
  155. # if !defined(BOOST_MSVC) || BOOST_MSVC > 1300
  156. ;
  157. # else
  158. {
  159. return this->slice(
  160. slice_bound<T>::type(start)
  161. , slice_bound<V>::type(end));
  162. }
  163. # endif
  164. private: // def visitation for adding callable objects as class methods
  165. template <class ClassT, class DocStringT>
  166. void visit(ClassT& cl, char const* name, python::detail::def_helper<DocStringT> const& helper) const
  167. {
  168. // It's too late to specify anything other than docstrings if
  169. // the callable object is already wrapped.
  170. BOOST_STATIC_ASSERT(
  171. (is_same<char const*,DocStringT>::value
  172. || detail::is_string_literal<DocStringT const>::value));
  173. objects::add_to_namespace(cl, name, this->derived_visitor(), helper.doc());
  174. }
  175. friend class python::def_visitor_access;
  176. private:
  177. // there is a confirmed CWPro8 codegen bug here. We prevent the
  178. // early destruction of a temporary by binding a named object
  179. // instead.
  180. # if __MWERKS__ < 0x3000 || __MWERKS__ > 0x3003
  181. typedef object const& object_cref2;
  182. # else
  183. typedef object const object_cref2;
  184. # endif
  185. };
  186. // VC6 and VC7 require this base class in order to generate the
  187. // correct copy constructor for object. We can't define it there
  188. // explicitly or it will complain of ambiguity.
  189. struct object_base : object_operators<object>
  190. {
  191. // copy constructor without NULL checking, for efficiency.
  192. inline object_base(object_base const&);
  193. inline object_base(PyObject* ptr);
  194. inline object_base& operator=(object_base const& rhs);
  195. inline ~object_base();
  196. // Underlying object access -- returns a borrowed reference
  197. inline PyObject* ptr() const;
  198. inline bool is_none() const;
  199. private:
  200. PyObject* m_ptr;
  201. };
  202. # ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
  203. template <class T, class U>
  204. struct is_derived_impl
  205. {
  206. static T x;
  207. template <class X>
  208. static X* to_pointer(X const&);
  209. static char test(U const*);
  210. typedef char (&no)[2];
  211. static no test(...);
  212. BOOST_STATIC_CONSTANT(bool, value = sizeof(test(to_pointer(x))) == 1);
  213. };
  214. template <class T, class U>
  215. struct is_derived
  216. : mpl::bool_<is_derived_impl<T,U>::value>
  217. {};
  218. # else
  219. template <class T, class U>
  220. struct is_derived
  221. : is_convertible<
  222. typename remove_reference<T>::type*
  223. , U const*
  224. >
  225. {};
  226. # endif
  227. template <class T>
  228. typename objects::unforward_cref<T>::type do_unforward_cref(T const& x)
  229. {
  230. # if BOOST_WORKAROUND(__GNUC__, == 2)
  231. typedef typename objects::unforward_cref<T>::type ret;
  232. return ret(x);
  233. # else
  234. return x;
  235. # endif
  236. }
  237. # if BOOST_WORKAROUND(__GNUC__, == 2)
  238. // GCC 2.x has non-const string literals; this hacks around that problem.
  239. template <unsigned N>
  240. char const (& do_unforward_cref(char const(&x)[N]) )[N]
  241. {
  242. return x;
  243. }
  244. # endif
  245. class object;
  246. template <class T>
  247. PyObject* object_base_initializer(T const& x)
  248. {
  249. typedef typename is_derived<
  250. BOOST_DEDUCED_TYPENAME objects::unforward_cref<T>::type
  251. , object
  252. >::type is_obj;
  253. return object_initializer<
  254. BOOST_DEDUCED_TYPENAME unwrap_reference<T>::type
  255. >::get(
  256. x
  257. , is_obj()
  258. );
  259. }
  260. class object : public object_base
  261. {
  262. public:
  263. // default constructor creates a None object
  264. object();
  265. // explicit conversion from any C++ object to Python
  266. template <class T>
  267. explicit object(
  268. T const& x
  269. # if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
  270. // use some SFINAE to un-confuse MSVC about its
  271. // copy-initialization ambiguity claim.
  272. , typename mpl::if_<is_proxy<T>,int&,int>::type* = 0
  273. # endif
  274. )
  275. : object_base(object_base_initializer(x))
  276. {
  277. }
  278. // Throw error_already_set() if the handle is null.
  279. BOOST_PYTHON_DECL explicit object(handle<> const&);
  280. private:
  281. public: // implementation detail -- for internal use only
  282. explicit object(detail::borrowed_reference);
  283. explicit object(detail::new_reference);
  284. explicit object(detail::new_non_null_reference);
  285. };
  286. // Macros for forwarding constructors in classes derived from
  287. // object. Derived classes will usually want these as an
  288. // implementation detail
  289. # define BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS_(derived, base) \
  290. inline explicit derived(::boost::python::detail::borrowed_reference p) \
  291. : base(p) {} \
  292. inline explicit derived(::boost::python::detail::new_reference p) \
  293. : base(p) {} \
  294. inline explicit derived(::boost::python::detail::new_non_null_reference p) \
  295. : base(p) {}
  296. # if !defined(BOOST_MSVC) || BOOST_MSVC >= 1300
  297. # define BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS_
  298. # else
  299. // MSVC6 has a bug which causes an explicit template constructor to
  300. // be preferred over an appropriate implicit conversion operator
  301. // declared on the argument type. Normally, that would cause a
  302. // runtime failure when using extract<T> to extract a type with a
  303. // templated constructor. This additional constructor will turn that
  304. // runtime failure into an ambiguity error at compile-time due to
  305. // the lack of partial ordering, or at least a link-time error if no
  306. // generalized template constructor is declared.
  307. # define BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS(derived, base) \
  308. BOOST_PYTHON_FORWARD_OBJECT_CONSTRUCTORS_(derived, base) \
  309. template <class T> \
  310. explicit derived(extract<T> const&);
  311. # endif
  312. //
  313. // object_initializer -- get the handle to construct the object with,
  314. // based on whether T is a proxy or derived from object
  315. //
  316. template <bool is_proxy = false, bool is_object_manager = false>
  317. struct object_initializer_impl
  318. {
  319. static PyObject*
  320. get(object const& x, mpl::true_)
  321. {
  322. return python::incref(x.ptr());
  323. }
  324. template <class T>
  325. static PyObject*
  326. get(T const& x, mpl::false_)
  327. {
  328. return python::incref(converter::arg_to_python<T>(x).get());
  329. }
  330. };
  331. template <>
  332. struct object_initializer_impl<true, false>
  333. {
  334. template <class Policies>
  335. static PyObject*
  336. get(proxy<Policies> const& x, mpl::false_)
  337. {
  338. return python::incref(x.operator object().ptr());
  339. }
  340. };
  341. template <>
  342. struct object_initializer_impl<false, true>
  343. {
  344. template <class T, class U>
  345. static PyObject*
  346. get(T const& x, U)
  347. {
  348. return python::incref(get_managed_object(x, boost::python::tag));
  349. }
  350. };
  351. template <>
  352. struct object_initializer_impl<true, true>
  353. {}; // empty implementation should cause an error
  354. template <class T>
  355. struct object_initializer : object_initializer_impl<
  356. is_proxy<T>::value
  357. , converter::is_object_manager<T>::value
  358. >
  359. {};
  360. }
  361. using api::object;
  362. template <class T> struct extract;
  363. //
  364. // implementation
  365. //
  366. namespace detail
  367. {
  368. class call_proxy
  369. {
  370. public:
  371. call_proxy(object target) : m_target(target) {}
  372. operator object() const { return m_target;}
  373. private:
  374. object m_target;
  375. };
  376. class kwds_proxy : public call_proxy
  377. {
  378. public:
  379. kwds_proxy(object o = object()) : call_proxy(o) {}
  380. };
  381. class args_proxy : public call_proxy
  382. {
  383. public:
  384. args_proxy(object o) : call_proxy(o) {}
  385. kwds_proxy operator* () const { return kwds_proxy(*this);}
  386. };
  387. }
  388. template <typename U>
  389. detail::args_proxy api::object_operators<U>::operator* () const
  390. {
  391. object_cref2 x = *static_cast<U const*>(this);
  392. return boost::python::detail::args_proxy(x);
  393. }
  394. template <typename U>
  395. object api::object_operators<U>::operator()(detail::args_proxy const &args) const
  396. {
  397. U const& self = *static_cast<U const*>(this);
  398. PyObject *result = PyObject_Call(get_managed_object(self, boost::python::tag),
  399. args.operator object().ptr(),
  400. 0);
  401. return object(boost::python::detail::new_reference(result));
  402. }
  403. template <typename U>
  404. object api::object_operators<U>::operator()(detail::args_proxy const &args,
  405. detail::kwds_proxy const &kwds) const
  406. {
  407. U const& self = *static_cast<U const*>(this);
  408. PyObject *result = PyObject_Call(get_managed_object(self, boost::python::tag),
  409. args.operator object().ptr(),
  410. kwds.operator object().ptr());
  411. return object(boost::python::detail::new_reference(result));
  412. }
  413. template <typename U>
  414. template <class T>
  415. object api::object_operators<U>::contains(T const& key) const
  416. {
  417. return this->attr("__contains__")(object(key));
  418. }
  419. inline object::object()
  420. : object_base(python::incref(Py_None))
  421. {}
  422. // copy constructor without NULL checking, for efficiency
  423. inline api::object_base::object_base(object_base const& rhs)
  424. : m_ptr(python::incref(rhs.m_ptr))
  425. {}
  426. inline api::object_base::object_base(PyObject* p)
  427. : m_ptr(p)
  428. {}
  429. inline api::object_base& api::object_base::operator=(api::object_base const& rhs)
  430. {
  431. Py_INCREF(rhs.m_ptr);
  432. Py_DECREF(this->m_ptr);
  433. this->m_ptr = rhs.m_ptr;
  434. return *this;
  435. }
  436. inline api::object_base::~object_base()
  437. {
  438. Py_DECREF(m_ptr);
  439. }
  440. inline object::object(detail::borrowed_reference p)
  441. : object_base(python::incref((PyObject*)p))
  442. {}
  443. inline object::object(detail::new_reference p)
  444. : object_base(expect_non_null((PyObject*)p))
  445. {}
  446. inline object::object(detail::new_non_null_reference p)
  447. : object_base((PyObject*)p)
  448. {}
  449. inline PyObject* api::object_base::ptr() const
  450. {
  451. return m_ptr;
  452. }
  453. inline bool api::object_base::is_none() const
  454. {
  455. return (m_ptr == Py_None);
  456. }
  457. //
  458. // Converter specialization implementations
  459. //
  460. namespace converter
  461. {
  462. template <class T> struct object_manager_traits;
  463. template <>
  464. struct object_manager_traits<object>
  465. {
  466. BOOST_STATIC_CONSTANT(bool, is_specialized = true);
  467. static bool check(PyObject*) { return true; }
  468. static python::detail::new_non_null_reference adopt(PyObject* x)
  469. {
  470. return python::detail::new_non_null_reference(x);
  471. }
  472. #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
  473. static PyTypeObject const *get_pytype() {return 0;}
  474. #endif
  475. };
  476. }
  477. inline PyObject* get_managed_object(object const& x, tag_t)
  478. {
  479. return x.ptr();
  480. }
  481. }} // namespace boost::python
  482. # include <boost/python/slice_nil.hpp>
  483. #endif // OBJECT_CORE_DWA2002615_HPP