make_constructor.hpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. // Copyright David Abrahams 2001.
  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_CONSTRUCTOR_DWA20011221_HPP
  6. # define MAKE_CONSTRUCTOR_DWA20011221_HPP
  7. # include <boost/python/detail/prefix.hpp>
  8. # include <boost/python/default_call_policies.hpp>
  9. # include <boost/python/args.hpp>
  10. # include <boost/python/object_fwd.hpp>
  11. # include <boost/python/object/function_object.hpp>
  12. # include <boost/python/object/make_holder.hpp>
  13. # include <boost/python/object/pointer_holder.hpp>
  14. # include <boost/python/converter/context_result_converter.hpp>
  15. # include <boost/python/detail/caller.hpp>
  16. # include <boost/python/detail/none.hpp>
  17. # include <boost/mpl/size.hpp>
  18. # include <boost/mpl/int.hpp>
  19. # include <boost/mpl/push_front.hpp>
  20. # include <boost/mpl/pop_front.hpp>
  21. # include <boost/mpl/assert.hpp>
  22. namespace boost { namespace python {
  23. namespace detail
  24. {
  25. template <class T>
  26. struct install_holder : converter::context_result_converter
  27. {
  28. install_holder(PyObject* args_)
  29. : m_self(PyTuple_GetItem(args_, 0)) {}
  30. PyObject* operator()(T x) const
  31. {
  32. dispatch(x, is_pointer<T>());
  33. return none();
  34. }
  35. private:
  36. template <class U>
  37. void dispatch(U* x, mpl::true_) const
  38. {
  39. std::auto_ptr<U> owner(x);
  40. dispatch(owner, mpl::false_());
  41. }
  42. template <class Ptr>
  43. void dispatch(Ptr x, mpl::false_) const
  44. {
  45. typedef typename pointee<Ptr>::type value_type;
  46. typedef objects::pointer_holder<Ptr,value_type> holder;
  47. typedef objects::instance<holder> instance_t;
  48. void* memory = holder::allocate(this->m_self, offsetof(instance_t, storage), sizeof(holder));
  49. try {
  50. (new (memory) holder(x))->install(this->m_self);
  51. }
  52. catch(...) {
  53. holder::deallocate(this->m_self, memory);
  54. throw;
  55. }
  56. }
  57. PyObject* m_self;
  58. };
  59. struct constructor_result_converter
  60. {
  61. template <class T>
  62. struct apply
  63. {
  64. typedef install_holder<T> type;
  65. };
  66. };
  67. template <class BaseArgs, class Offset>
  68. struct offset_args
  69. {
  70. offset_args(BaseArgs base_) : base(base_) {}
  71. BaseArgs base;
  72. };
  73. template <int N, class BaseArgs, class Offset>
  74. inline PyObject* get(mpl::int_<N>, offset_args<BaseArgs,Offset> const& args_)
  75. {
  76. return get(mpl::int_<(N+Offset::value)>(), args_.base);
  77. }
  78. template <class BaseArgs, class Offset>
  79. inline unsigned arity(offset_args<BaseArgs,Offset> const& args_)
  80. {
  81. return arity(args_.base) - Offset::value;
  82. }
  83. template <class BasePolicy_ = default_call_policies>
  84. struct constructor_policy : BasePolicy_
  85. {
  86. constructor_policy(BasePolicy_ base) : BasePolicy_(base) {}
  87. // If the BasePolicy_ supplied a result converter it would be
  88. // ignored; issue an error if it's not the default.
  89. BOOST_MPL_ASSERT_MSG(
  90. (is_same<
  91. typename BasePolicy_::result_converter
  92. , default_result_converter
  93. >::value)
  94. , MAKE_CONSTRUCTOR_SUPPLIES_ITS_OWN_RESULT_CONVERTER_THAT_WOULD_OVERRIDE_YOURS
  95. , (typename BasePolicy_::result_converter)
  96. );
  97. typedef constructor_result_converter result_converter;
  98. typedef offset_args<typename BasePolicy_::argument_package, mpl::int_<1> > argument_package;
  99. };
  100. template <class InnerSignature>
  101. struct outer_constructor_signature
  102. {
  103. typedef typename mpl::pop_front<InnerSignature>::type inner_args;
  104. typedef typename mpl::push_front<inner_args,object>::type outer_args;
  105. typedef typename mpl::push_front<outer_args,void>::type type;
  106. };
  107. // ETI workaround
  108. template <>
  109. struct outer_constructor_signature<int>
  110. {
  111. typedef int type;
  112. };
  113. //
  114. // These helper functions for make_constructor (below) do the raw work
  115. // of constructing a Python object from some invokable entity. See
  116. // <boost/python/detail/caller.hpp> for more information about how
  117. // the Sig arguments is used.
  118. //
  119. // @group make_constructor_aux {
  120. template <class F, class CallPolicies, class Sig>
  121. object make_constructor_aux(
  122. F f // An object that can be invoked by detail::invoke()
  123. , CallPolicies const& p // CallPolicies to use in the invocation
  124. , Sig const& // An MPL sequence of argument types expected by F
  125. )
  126. {
  127. typedef typename outer_constructor_signature<Sig>::type outer_signature;
  128. typedef constructor_policy<CallPolicies> inner_policy;
  129. return objects::function_object(
  130. objects::py_function(
  131. detail::caller<F,inner_policy,Sig>(f, inner_policy(p))
  132. , outer_signature()
  133. )
  134. );
  135. }
  136. // As above, except that it accepts argument keywords. NumKeywords
  137. // is used only for a compile-time assertion to make sure the user
  138. // doesn't pass more keywords than the function can accept. To
  139. // disable all checking, pass mpl::int_<0> for NumKeywords.
  140. template <class F, class CallPolicies, class Sig, class NumKeywords>
  141. object make_constructor_aux(
  142. F f
  143. , CallPolicies const& p
  144. , Sig const&
  145. , detail::keyword_range const& kw // a [begin,end) pair of iterators over keyword names
  146. , NumKeywords // An MPL integral type wrapper: the size of kw
  147. )
  148. {
  149. enum { arity = mpl::size<Sig>::value - 1 };
  150. typedef typename detail::error::more_keywords_than_function_arguments<
  151. NumKeywords::value, arity
  152. >::too_many_keywords assertion;
  153. typedef typename outer_constructor_signature<Sig>::type outer_signature;
  154. typedef constructor_policy<CallPolicies> inner_policy;
  155. return objects::function_object(
  156. objects::py_function(
  157. detail::caller<F,inner_policy,Sig>(f, inner_policy(p))
  158. , outer_signature()
  159. )
  160. , kw
  161. );
  162. }
  163. // }
  164. //
  165. // These dispatch functions are used to discriminate between the
  166. // cases when the 3rd argument is keywords or when it is a
  167. // signature.
  168. //
  169. // @group Helpers for make_constructor when called with 3 arguments. {
  170. //
  171. template <class F, class CallPolicies, class Keywords>
  172. object make_constructor_dispatch(F f, CallPolicies const& policies, Keywords const& kw, mpl::true_)
  173. {
  174. return detail::make_constructor_aux(
  175. f
  176. , policies
  177. , detail::get_signature(f)
  178. , kw.range()
  179. , mpl::int_<Keywords::size>()
  180. );
  181. }
  182. template <class F, class CallPolicies, class Signature>
  183. object make_constructor_dispatch(F f, CallPolicies const& policies, Signature const& sig, mpl::false_)
  184. {
  185. return detail::make_constructor_aux(
  186. f
  187. , policies
  188. , sig
  189. );
  190. }
  191. // }
  192. }
  193. // These overloaded functions wrap a function or member function
  194. // pointer as a Python object, using optional CallPolicies,
  195. // Keywords, and/or Signature. @group {
  196. //
  197. template <class F>
  198. object make_constructor(F f)
  199. {
  200. return detail::make_constructor_aux(
  201. f,default_call_policies(), detail::get_signature(f));
  202. }
  203. template <class F, class CallPolicies>
  204. object make_constructor(F f, CallPolicies const& policies)
  205. {
  206. return detail::make_constructor_aux(
  207. f, policies, detail::get_signature(f));
  208. }
  209. template <class F, class CallPolicies, class KeywordsOrSignature>
  210. object make_constructor(
  211. F f
  212. , CallPolicies const& policies
  213. , KeywordsOrSignature const& keywords_or_signature)
  214. {
  215. typedef typename
  216. detail::is_reference_to_keywords<KeywordsOrSignature&>::type
  217. is_kw;
  218. return detail::make_constructor_dispatch(
  219. f
  220. , policies
  221. , keywords_or_signature
  222. , is_kw()
  223. );
  224. }
  225. template <class F, class CallPolicies, class Keywords, class Signature>
  226. object make_constructor(
  227. F f
  228. , CallPolicies const& policies
  229. , Keywords const& kw
  230. , Signature const& sig
  231. )
  232. {
  233. return detail::make_constructor_aux(
  234. f
  235. , policies
  236. , sig
  237. , kw.range()
  238. , mpl::int_<Keywords::size>()
  239. );
  240. }
  241. // }
  242. }}
  243. #endif // MAKE_CONSTRUCTOR_DWA20011221_HPP