summaryrefslogtreecommitdiff
path: root/boost/python/signature.hpp
blob: 9b323a2823fbdbce1d34ee815bd1c985bcb07545 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
///////////////////////////////////////////////////////////////////////////////
//
// Copyright David Abrahams 2002, Joel de Guzman, 2002.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
///////////////////////////////////////////////////////////////////////////////
#if !defined(BOOST_PP_IS_ITERATING)

# ifndef SIGNATURE_JDG20020813_HPP
#  define SIGNATURE_JDG20020813_HPP

# include <boost/python/detail/prefix.hpp>

# include <boost/mpl/if.hpp>

#  include <boost/python/detail/preprocessor.hpp>
#  include <boost/python/detail/type_traits.hpp>
#  include <boost/preprocessor/repeat.hpp>
#  include <boost/preprocessor/enum.hpp>
#  include <boost/preprocessor/enum_params.hpp>
#  include <boost/preprocessor/empty.hpp>
#  include <boost/preprocessor/arithmetic/sub.hpp>
#  include <boost/preprocessor/iterate.hpp>
#  include <boost/python/detail/type_list.hpp>

#  include <boost/preprocessor/debug/line.hpp>
#  include <boost/preprocessor/arithmetic/sub.hpp>
#  include <boost/preprocessor/arithmetic/inc.hpp>
#  include <boost/preprocessor/repetition/enum_trailing_params.hpp>

# define BOOST_PYTHON_LIST_INC(n)        \
   BOOST_PP_CAT(mpl::vector, BOOST_PP_INC(n))

///////////////////////////////////////////////////////////////////////////////
namespace boost { namespace python { namespace detail {

// A metafunction returning C1 if C1 is derived from C2, and C2
// otherwise
template <class C1, class C2>
struct most_derived
{
    typedef typename mpl::if_<
        detail::is_convertible<C1*,C2*>
      , C1
      , C2
    >::type type;
};

//  The following macros generate expansions for::
//
//      template <class RT, class T0... class TN>
//      inline mpl::vector<RT, T0...TN>
//      get_signature(RT(BOOST_PYTHON_FN_CC *)(T0...TN), void* = 0)
//      {
//          return mpl::list<RT, T0...TN>();
//      }
//
//    where BOOST_PYTHON_FN_CC is a calling convention keyword, can be
//
//        empty, for default calling convention
//        __cdecl (if BOOST_PYTHON_ENABLE_CDECL is defined)
//        __stdcall (if BOOST_PYTHON_ENABLE_STDCALL is defined)
//        __fastcall (if BOOST_PYTHON_ENABLE_FASTCALL is defined)
//
//   And, for an appropriate assortment of cv-qualifications::
//
//      template <class RT, class ClassT, class T0... class TN>
//      inline mpl::vector<RT, ClassT&, T0...TN>
//      get_signature(RT(BOOST_PYTHON_FN_CC ClassT::*)(T0...TN) cv))
//      {
//          return mpl::list<RT, ClassT&, T0...TN>();
//      }
//
//      template <class Target, class RT, class ClassT, class T0... class TN>
//      inline mpl::vector<
//          RT
//        , typename most_derived<Target, ClassT>::type&
//        , T0...TN
//      >
//      get_signature(RT(BOOST_PYTHON_FN_CC ClassT::*)(T0...TN) cv), Target*)
//      {
//          return mpl::list<RT, ClassT&, T0...TN>();
//      }
//
//  There are two forms for invoking get_signature::
//
//      get_signature(f)
//
//  and ::
//
//      get_signature(f,(Target*)0)
//
//  These functions extract the return type, class (for member
//  functions) and arguments of the input signature and stuff them in
//  an mpl type sequence (the calling convention is dropped).
//  Note that cv-qualification is dropped from
//  the "hidden this" argument of member functions; that is a
//  necessary sacrifice to ensure that an lvalue from_python converter
//  is used.  A pointer is not used so that None will be rejected for
//  overload resolution.
//
//  The second form of get_signature essentially downcasts the "hidden
//  this" argument of member functions to Target, because the function
//  may actually be a member of a base class which is not wrapped, and
//  in that case conversion from python would fail.
//
// @group {

// 'default' calling convention

#  define BOOST_PYTHON_FN_CC
#  define BOOST_PYTHON_FN_CC_IS_DEFAULT

#  define BOOST_PP_ITERATION_PARAMS_1                                   \
    (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/signature.hpp>))

#  include BOOST_PP_ITERATE()

#  undef BOOST_PYTHON_FN_CC
#  undef BOOST_PYTHON_FN_CC_IS_DEFAULT

// __cdecl calling convention

#  if defined(BOOST_PYTHON_ENABLE_CDECL)

#   define BOOST_PYTHON_FN_CC __cdecl
#   define BOOST_PYTHON_FN_CC_IS_CDECL

#   define BOOST_PP_ITERATION_PARAMS_1                                   \
     (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/signature.hpp>))

#   include BOOST_PP_ITERATE()

#   undef BOOST_PYTHON_FN_CC
#   undef BOOST_PYTHON_FN_CC_IS_CDECL

#  endif // defined(BOOST_PYTHON_ENABLE_CDECL)

// __stdcall calling convention

#  if defined(BOOST_PYTHON_ENABLE_STDCALL)

#   define BOOST_PYTHON_FN_CC __stdcall
#   define BOOST_PYTHON_FN_CC_IS_STDCALL

#   define BOOST_PP_ITERATION_PARAMS_1                                   \
     (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/signature.hpp>))

#   include BOOST_PP_ITERATE()

#   undef BOOST_PYTHON_FN_CC
#   undef BOOST_PYTHON_FN_CC_IS_STDCALL

#  endif // defined(BOOST_PYTHON_ENABLE_STDCALL)

// __fastcall calling convention

#  if defined(BOOST_PYTHON_ENABLE_FASTCALL)

#   define BOOST_PYTHON_FN_CC __fastcall
#   define BOOST_PYTHON_FN_CC_IS_FASTCALL

#   define BOOST_PP_ITERATION_PARAMS_1                                   \
     (3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/signature.hpp>))

#   include BOOST_PP_ITERATE()

#   undef BOOST_PYTHON_FN_CC_IS_FASTCALL
#   undef BOOST_PYTHON_FN_CC

#  endif // defined(BOOST_PYTHON_ENABLE_FASTCALL)

#  undef BOOST_PYTHON_LIST_INC

// }

}}} // namespace boost::python::detail


# endif // SIGNATURE_JDG20020813_HPP

// For gcc 4.4 compatability, we must include the
// BOOST_PP_ITERATION_DEPTH test inside an #else clause.
#else // BOOST_PP_IS_ITERATING
#if BOOST_PP_ITERATION_DEPTH() == 1 // defined(BOOST_PP_IS_ITERATING)

# define N BOOST_PP_ITERATION()

   // as 'get_signature(RT(*)(T0...TN), void* = 0)' is the same
   // function as 'get_signature(RT(__cdecl *)(T0...TN), void* = 0)',
   // we don't define it multiple times (i.e. for __cdecl, __stdcall ...)
#  if defined(BOOST_PYTHON_FN_CC_IS_DEFAULT)

template <
    class RT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class T)>
inline BOOST_PYTHON_LIST_INC(N)<
    RT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)>
get_signature(RT(BOOST_PYTHON_FN_CC *)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)), void* = 0)
{
    return BOOST_PYTHON_LIST_INC(N)<
            RT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)
        >();
}

#  endif  // BOOST_PYTHON_FN_CC_IS_DEFAULT

# undef N

# define BOOST_PP_ITERATION_PARAMS_2 \
    (3, (0, 3, <boost/python/signature.hpp>))
# include BOOST_PP_ITERATE()

#else  // BOOST_PP_ITERATION_DEPTH() != 1

# define N BOOST_PP_RELATIVE_ITERATION(1)
# define Q BOOST_PYTHON_CV_QUALIFIER(BOOST_PP_ITERATION())

#  if defined(BOOST_PYTHON_FN_CC_IS_DEFAULT)

template <
    class RT, class ClassT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class T)>
inline BOOST_PYTHON_LIST_INC(BOOST_PP_INC(N))<
    RT, ClassT& BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)>
get_signature(RT(BOOST_PYTHON_FN_CC ClassT::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)) Q)
{
    return BOOST_PYTHON_LIST_INC(BOOST_PP_INC(N))<
            RT, ClassT& BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)
        >();
}

template <
    class Target
  , class RT
  , class ClassT
    BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class T)
>
inline BOOST_PYTHON_LIST_INC(BOOST_PP_INC(N))<
    RT
  , typename most_derived<Target, ClassT>::type&
    BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)
>
get_signature(
    RT(BOOST_PYTHON_FN_CC ClassT::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)) Q
  , Target*
)
{
    return BOOST_PYTHON_LIST_INC(BOOST_PP_INC(N))<
        RT
      , BOOST_DEDUCED_TYPENAME most_derived<Target, ClassT>::type&
        BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)
    >();
}

#  endif  // BOOST_PYTHON_FN_CC_IS_DEFAULT

# undef Q
# undef N

#endif // BOOST_PP_ITERATION_DEPTH()
#endif // !defined(BOOST_PP_IS_ITERATING)