Skip to content

Commit 5418a66

Browse files
committed
Support different MS calling conventions, thanks to Nicolas Lelong.
Closes #3833. [SVN r59265]
1 parent 33408d2 commit 5418a66

4 files changed

Lines changed: 482 additions & 0 deletions

File tree

test/calling_conventions.cpp

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
//
2+
// adapted from bind_stdcall_test.cpp - test for bind.hpp + __stdcall (free functions)
3+
// The purpose of this simple test is to determine if a function can be
4+
// called from Python with the various existing calling conventions
5+
//
6+
// Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
7+
//
8+
// Distributed under the Boost Software License, Version 1.0. (See
9+
// accompanying file LICENSE_1_0.txt or copy at
10+
// http://www.boost.org/LICENSE_1_0.txt)
11+
//
12+
13+
#if !defined(TEST_INCLUDE_RECURSION)
14+
15+
#define TEST_INCLUDE_RECURSION
16+
17+
//------------------------------------------------------------------------------
18+
// this section is the main body of the test extension module
19+
20+
#define BOOST_PYTHON_ENABLE_CDECL
21+
#define BOOST_PYTHON_ENABLE_STDCALL
22+
#define BOOST_PYTHON_ENABLE_FASTCALL
23+
#include <boost/preprocessor/cat.hpp>
24+
#include <boost/preprocessor/stringize.hpp>
25+
#include <boost/python.hpp>
26+
using namespace boost::python;
27+
28+
// first define test functions for every calling convention
29+
30+
#define TEST_DECLARE_FUNCTIONS
31+
32+
#define TESTED_CALLING_CONVENTION __cdecl
33+
#include "calling_conventions.cpp"
34+
#undef TESTED_CALLING_CONVENTION
35+
36+
#define TESTED_CALLING_CONVENTION __stdcall
37+
#include "calling_conventions.cpp"
38+
#undef TESTED_CALLING_CONVENTION
39+
40+
#define TESTED_CALLING_CONVENTION __fastcall
41+
#include "calling_conventions.cpp"
42+
#undef TESTED_CALLING_CONVENTION
43+
44+
#undef TEST_DECLARE_FUNCTIONS
45+
46+
// then create a module wrapping the defined functions for every calling convention
47+
48+
BOOST_PYTHON_MODULE( calling_conventions_ext )
49+
{
50+
51+
#define TEST_WRAP_FUNCTIONS
52+
53+
#define TESTED_CALLING_CONVENTION __cdecl
54+
#include "calling_conventions.cpp"
55+
#undef TESTED_CALLING_CONVENTION
56+
57+
#define TESTED_CALLING_CONVENTION __stdcall
58+
#include "calling_conventions.cpp"
59+
#undef TESTED_CALLING_CONVENTION
60+
61+
#define TESTED_CALLING_CONVENTION __fastcall
62+
#include "calling_conventions.cpp"
63+
#undef TESTED_CALLING_CONVENTION
64+
65+
#undef TEST_WRAP_FUNCTIONS
66+
67+
}
68+
69+
#else // !defined(TEST_INCLUDE_RECURSION)
70+
71+
//------------------------------------------------------------------------------
72+
// this section defines the functions to be wrapped
73+
74+
# if defined(TEST_DECLARE_FUNCTIONS)
75+
76+
# if !defined(TESTED_CALLING_CONVENTION)
77+
# error "One calling convention must be defined"
78+
# endif // !defined(TESTED_CALLING_CONVENTION)
79+
80+
namespace BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION) {
81+
82+
long TESTED_CALLING_CONVENTION f_0()
83+
{
84+
return 17041L;
85+
}
86+
87+
long TESTED_CALLING_CONVENTION f_1(long a)
88+
{
89+
return a;
90+
}
91+
92+
long TESTED_CALLING_CONVENTION f_2(long a, long b)
93+
{
94+
return a + 10 * b;
95+
}
96+
97+
long TESTED_CALLING_CONVENTION f_3(long a, long b, long c)
98+
{
99+
return a + 10 * b + 100 * c;
100+
}
101+
102+
long TESTED_CALLING_CONVENTION f_4(long a, long b, long c, long d)
103+
{
104+
return a + 10 * b + 100 * c + 1000 * d;
105+
}
106+
107+
long TESTED_CALLING_CONVENTION f_5(long a, long b, long c, long d, long e)
108+
{
109+
return a + 10 * b + 100 * c + 1000 * d + 10000 * e;
110+
}
111+
112+
long TESTED_CALLING_CONVENTION f_6(long a, long b, long c, long d, long e, long f)
113+
{
114+
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f;
115+
}
116+
117+
long TESTED_CALLING_CONVENTION f_7(long a, long b, long c, long d, long e, long f, long g)
118+
{
119+
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g;
120+
}
121+
122+
long TESTED_CALLING_CONVENTION f_8(long a, long b, long c, long d, long e, long f, long g, long h)
123+
{
124+
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g + 10000000 * h;
125+
}
126+
127+
long TESTED_CALLING_CONVENTION f_9(long a, long b, long c, long d, long e, long f, long g, long h, long i)
128+
{
129+
return a + 10 * b + 100 * c + 1000 * d + 10000 * e + 100000 * f + 1000000 * g + 10000000 * h + 100000000 * i;
130+
}
131+
132+
} // namespace test##TESTED_CALLING_CONVENTION
133+
134+
# endif // defined(TEST_DECLARE_FUNCTIONS)
135+
136+
//------------------------------------------------------------------------------
137+
// this section wraps the functions
138+
139+
# if defined(TEST_WRAP_FUNCTIONS)
140+
141+
# if !defined(TESTED_CALLING_CONVENTION)
142+
# error "One calling convention must be defined"
143+
# endif // !defined(TESTED_CALLING_CONVENTION)
144+
145+
def("f_0" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_0);
146+
def("f_1" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_1);
147+
def("f_2" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_2);
148+
def("f_3" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_3);
149+
def("f_4" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_4);
150+
def("f_5" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_5);
151+
def("f_6" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_6);
152+
def("f_7" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_7);
153+
def("f_8" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_8);
154+
def("f_9" BOOST_PP_STRINGIZE(TESTED_CALLING_CONVENTION), &BOOST_PP_CAT(test, TESTED_CALLING_CONVENTION)::f_9);
155+
156+
# endif // defined(TEST_WRAP_FUNCTIONS)
157+
158+
#endif // !defined(TEST_INCLUDE_RECURSION)

test/calling_conventions.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Copyright Nicolas Lelong, 2010. Distributed under the Boost
2+
# Software License, Version 1.0 (See accompanying
3+
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4+
"""
5+
>>> from calling_conventions_ext import *
6+
>>> f_0__cdecl()
7+
17041
8+
>>> f_1__cdecl(1)
9+
1
10+
>>> f_2__cdecl(1, 2)
11+
21
12+
>>> f_3__cdecl(1, 2, 3)
13+
321
14+
>>> f_4__cdecl(1, 2, 3, 4)
15+
4321
16+
>>> f_5__cdecl(1, 2, 3, 4, 5)
17+
54321
18+
>>> f_6__cdecl(1, 2, 3, 4, 5, 6)
19+
654321
20+
>>> f_7__cdecl(1, 2, 3, 4, 5, 6, 7)
21+
7654321
22+
>>> f_8__cdecl(1, 2, 3, 4, 5, 6, 7, 8)
23+
87654321
24+
>>> f_9__cdecl(1, 2, 3, 4, 5, 6, 7, 8, 9)
25+
987654321
26+
>>> f_0__stdcall()
27+
17041
28+
>>> f_1__stdcall(1)
29+
1
30+
>>> f_2__stdcall(1, 2)
31+
21
32+
>>> f_3__stdcall(1, 2, 3)
33+
321
34+
>>> f_4__stdcall(1, 2, 3, 4)
35+
4321
36+
>>> f_5__stdcall(1, 2, 3, 4, 5)
37+
54321
38+
>>> f_6__stdcall(1, 2, 3, 4, 5, 6)
39+
654321
40+
>>> f_7__stdcall(1, 2, 3, 4, 5, 6, 7)
41+
7654321
42+
>>> f_8__stdcall(1, 2, 3, 4, 5, 6, 7, 8)
43+
87654321
44+
>>> f_9__stdcall(1, 2, 3, 4, 5, 6, 7, 8, 9)
45+
987654321
46+
>>> f_0__fastcall()
47+
17041
48+
>>> f_1__fastcall(1)
49+
1
50+
>>> f_2__fastcall(1, 2)
51+
21
52+
>>> f_3__fastcall(1, 2, 3)
53+
321
54+
>>> f_4__fastcall(1, 2, 3, 4)
55+
4321
56+
>>> f_5__fastcall(1, 2, 3, 4, 5)
57+
54321
58+
>>> f_6__fastcall(1, 2, 3, 4, 5, 6)
59+
654321
60+
>>> f_7__fastcall(1, 2, 3, 4, 5, 6, 7)
61+
7654321
62+
>>> f_8__fastcall(1, 2, 3, 4, 5, 6, 7, 8)
63+
87654321
64+
>>> f_9__fastcall(1, 2, 3, 4, 5, 6, 7, 8, 9)
65+
987654321
66+
"""
67+
68+
def run(args = None):
69+
import sys
70+
import doctest
71+
72+
if args is not None:
73+
sys.argv = args
74+
return doctest.testmod(sys.modules.get(__name__))
75+
76+
if __name__ == '__main__':
77+
print "running..."
78+
import sys
79+
status = run()[0]
80+
if (status == 0): print "Done."
81+
sys.exit(status)

0 commit comments

Comments
 (0)