source: NonGTP/Boost/boost/python/make_constructor.hpp @ 857

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