Skip to content

Commit 3ad52bc

Browse files
committed
Support different MS calling conventions, thanks to Nicolas Lelong.
Closes #3833. [SVN r59247]
1 parent 4f6a37f commit 3ad52bc

File tree

5 files changed

+116
-11
lines changed

5 files changed

+116
-11
lines changed

doc/v2/configuration.html

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,33 @@ <h2><a name="app-defined"></a>Application Defined Macros</h2>
106106
function from being treated as an exported symbol on platforms which
107107
support that distinction in-code</td>
108108
</tr>
109+
110+
<tr>
111+
<td valign="top"><code>BOOST_PYTHON_ENABLE_CDECL</code></td>
112+
113+
<td valign="top" align="center"><i>not&nbsp;defined</i></td>
114+
115+
<td valign="top">If defined, allows functions using the <code>__cdecl
116+
</code> calling convention to be wrapped.</td>
117+
</tr>
118+
119+
<tr>
120+
<td valign="top"><code>BOOST_PYTHON_ENABLE_STDCALL</code></td>
121+
122+
<td valign="top" align="center"><i>not&nbsp;defined</i></td>
123+
124+
<td valign="top">If defined, allows functions using the <code>__stdcall
125+
</code> calling convention to be wrapped.</td>
126+
</tr>
127+
128+
<tr>
129+
<td valign="top"><code>BOOST_PYTHON_ENABLE_FASTCALL</code></td>
130+
131+
<td valign="top" align="center"><i>not&nbsp;defined</i></td>
132+
133+
<td valign="top">If defined, allows functions using the <code>__fastcall
134+
</code> calling convention to be wrapped.</td>
135+
</tr>
109136
</table>
110137

111138
<h2><a name="lib-defined-impl"></a>Library Defined Implementation

include/boost/python/object/make_instance.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ struct make_instance_impl
2121
template <class Arg>
2222
static inline PyObject* execute(Arg& x)
2323
{
24-
BOOST_STATIC_ASSERT(is_class<T>::value);
24+
BOOST_MPL_ASSERT((mpl::or_<is_class<T>, is_union<T> >));
2525

2626
PyTypeObject* type = Derived::get_class_object(x);
2727

include/boost/python/object/pointer_holder.hpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535

3636
# include <boost/detail/workaround.hpp>
3737

38+
# include <boost/type_traits/remove_const.hpp>
39+
3840
namespace boost { namespace python {
3941

4042
template <class T> class wrapper;
@@ -122,26 +124,29 @@ inline pointer_holder_back_reference<Pointer,Value>::pointer_holder_back_referen
122124
template <class Pointer, class Value>
123125
void* pointer_holder<Pointer, Value>::holds(type_info dst_t, bool null_ptr_only)
124126
{
127+
typedef typename boost::remove_const< Value >::type non_const_value;
128+
125129
if (dst_t == python::type_id<Pointer>()
126130
&& !(null_ptr_only && get_pointer(this->m_p))
127131
)
128132
return &this->m_p;
129133

130-
Value* p
134+
Value* p0
131135
# if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
132136
= static_cast<Value*>( get_pointer(this->m_p) )
133137
# else
134138
= get_pointer(this->m_p)
135139
# endif
136140
;
137-
141+
non_const_value* p = const_cast<non_const_value*>( p0 );
142+
138143
if (p == 0)
139144
return 0;
140145

141146
if (void* wrapped = holds_wrapped(dst_t, p, p))
142147
return wrapped;
143148

144-
type_info src_t = python::type_id<Value>();
149+
type_info src_t = python::type_id<non_const_value>();
145150
return src_t == dst_t ? p : find_dynamic_type(p, src_t, dst_t);
146151
}
147152

include/boost/python/signature.hpp

Lines changed: 76 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,23 @@ struct most_derived
5252
//
5353
// template <class RT, class T0... class TN>
5454
// inline mpl::vector<RT, T0...TN>
55-
// get_signature(RT(*)(T0...TN), void* = 0)
55+
// get_signature(RT(BOOST_PYTHON_FN_CC *)(T0...TN), void* = 0)
5656
// {
5757
// return mpl::list<RT, T0...TN>();
5858
// }
5959
//
60+
// where BOOST_PYTHON_FN_CC is a calling convention keyword, can be
61+
//
62+
// empty, for default calling convention
63+
// __cdecl (if BOOST_PYTHON_ENABLE_CDECL is defined)
64+
// __stdcall (if BOOST_PYTHON_ENABLE_STDCALL is defined)
65+
// __fastcall (if BOOST_PYTHON_ENABLE_FASTCALL is defined)
66+
//
6067
// And, for an appropriate assortment of cv-qualifications::
6168
//
6269
// template <class RT, class ClassT, class T0... class TN>
6370
// inline mpl::vector<RT, ClassT&, T0...TN>
64-
// get_signature(RT(ClassT::*)(T0...TN) cv))
71+
// get_signature(RT(BOOST_PYTHON_FN_CC ClassT::*)(T0...TN) cv))
6572
// {
6673
// return mpl::list<RT, ClassT&, T0...TN>();
6774
// }
@@ -72,7 +79,7 @@ struct most_derived
7279
// , typename most_derived<Target, ClassT>::type&
7380
// , T0...TN
7481
// >
75-
// get_signature(RT(ClassT::*)(T0...TN) cv), Target*)
82+
// get_signature(RT(BOOST_PYTHON_FN_CC ClassT::*)(T0...TN) cv), Target*)
7683
// {
7784
// return mpl::list<RT, ClassT&, T0...TN>();
7885
// }
@@ -87,7 +94,8 @@ struct most_derived
8794
//
8895
// These functions extract the return type, class (for member
8996
// functions) and arguments of the input signature and stuff them in
90-
// an mpl type sequence. Note that cv-qualification is dropped from
97+
// an mpl type sequence (the calling convention is dropped).
98+
// Note that cv-qualification is dropped from
9199
// the "hidden this" argument of member functions; that is a
92100
// necessary sacrifice to ensure that an lvalue from_python converter
93101
// is used. A pointer is not used so that None will be rejected for
@@ -100,10 +108,64 @@ struct most_derived
100108
//
101109
// @group {
102110

111+
// 'default' calling convention
112+
113+
# define BOOST_PYTHON_FN_CC
114+
103115
# define BOOST_PP_ITERATION_PARAMS_1 \
104116
(3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/signature.hpp>))
105117

106118
# include BOOST_PP_ITERATE()
119+
120+
# undef BOOST_PYTHON_FN_CC
121+
122+
// __cdecl calling convention
123+
124+
# if defined(BOOST_PYTHON_ENABLE_CDECL)
125+
126+
# define BOOST_PYTHON_FN_CC __cdecl
127+
# define BOOST_PYTHON_FN_CC_IS_CDECL
128+
129+
# define BOOST_PP_ITERATION_PARAMS_1 \
130+
(3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/signature.hpp>))
131+
132+
# include BOOST_PP_ITERATE()
133+
134+
# undef BOOST_PYTHON_FN_CC
135+
# undef BOOST_PYTHON_FN_CC_IS_CDECL
136+
137+
# endif // defined(BOOST_PYTHON_ENABLE_CDECL)
138+
139+
// __stdcall calling convention
140+
141+
# if defined(BOOST_PYTHON_ENABLE_STDCALL)
142+
143+
# define BOOST_PYTHON_FN_CC __stdcall
144+
145+
# define BOOST_PP_ITERATION_PARAMS_1 \
146+
(3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/signature.hpp>))
147+
148+
# include BOOST_PP_ITERATE()
149+
150+
# undef BOOST_PYTHON_FN_CC
151+
152+
# endif // defined(BOOST_PYTHON_ENABLE_STDCALL)
153+
154+
// __fastcall calling convention
155+
156+
# if defined(BOOST_PYTHON_ENABLE_FASTCALL)
157+
158+
# define BOOST_PYTHON_FN_CC __fastcall
159+
160+
# define BOOST_PP_ITERATION_PARAMS_1 \
161+
(3, (0, BOOST_PYTHON_MAX_ARITY, <boost/python/signature.hpp>))
162+
163+
# include BOOST_PP_ITERATE()
164+
165+
# undef BOOST_PYTHON_FN_CC
166+
167+
# endif // defined(BOOST_PYTHON_ENABLE_FASTCALL)
168+
107169
# undef BOOST_PYTHON_LIST_INC
108170

109171
// }
@@ -120,17 +182,24 @@ struct most_derived
120182

121183
# define N BOOST_PP_ITERATION()
122184

185+
// as 'get_signature(RT(*)(T0...TN), void* = 0)' is the same
186+
// function as 'get_signature(RT(__cdecl *)(T0...TN), void* = 0)',
187+
// we don't define it twice
188+
# if !defined(BOOST_PYTHON_FN_CC_IS_CDECL)
189+
123190
template <
124191
class RT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class T)>
125192
inline BOOST_PYTHON_LIST_INC(N)<
126193
RT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)>
127-
get_signature(RT(*)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)), void* = 0)
194+
get_signature(RT(BOOST_PYTHON_FN_CC *)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)), void* = 0)
128195
{
129196
return BOOST_PYTHON_LIST_INC(N)<
130197
RT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)
131198
>();
132199
}
133200

201+
# endif // !defined(BOOST_PYTHON_FN_CC_IS_CDECL)
202+
134203
# undef N
135204

136205
# define BOOST_PP_ITERATION_PARAMS_2 \
@@ -146,7 +215,7 @@ template <
146215
class RT, class ClassT BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, class T)>
147216
inline BOOST_PYTHON_LIST_INC(BOOST_PP_INC(N))<
148217
RT, ClassT& BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)>
149-
get_signature(RT(ClassT::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)) Q)
218+
get_signature(RT(BOOST_PYTHON_FN_CC ClassT::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)) Q)
150219
{
151220
return BOOST_PYTHON_LIST_INC(BOOST_PP_INC(N))<
152221
RT, ClassT& BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)
@@ -165,7 +234,7 @@ inline BOOST_PYTHON_LIST_INC(BOOST_PP_INC(N))<
165234
BOOST_PP_ENUM_TRAILING_PARAMS_Z(1, N, T)
166235
>
167236
get_signature(
168-
RT(ClassT::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)) Q
237+
RT(BOOST_PYTHON_FN_CC ClassT::*)(BOOST_PP_ENUM_PARAMS_Z(1, N, T)) Q
169238
, Target*
170239
)
171240
{

test/Jamfile.v2

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,9 @@ bpl-test crossmod_opaque
184184
# bpl-test bienstman5 ;
185185
# }
186186

187+
[ bpl-test calling_conventions ]
188+
[ bpl-test calling_conventions_mf ]
189+
187190
# --- unit tests of library components ---
188191

189192
[ compile indirect_traits_test.cpp ]
@@ -196,6 +199,7 @@ bpl-test crossmod_opaque
196199

197200
[ compile string_literal.cpp ]
198201
[ py-compile borrowed.cpp ]
202+
[ py-compile union.cpp ]
199203
[ py-compile object_manager.cpp ]
200204
[ py-compile copy_ctor_mutates_rhs.cpp ]
201205

0 commit comments

Comments
 (0)