4
4
extern "C" {
5
5
#endif
6
6
7
- #ifndef HPY_UNIVERSAL_ABI
8
- /* It would be nice if we could include hpy.h WITHOUT bringing in all the
9
- stuff from Python.h, to make sure that people don't use the CPython API by
10
- mistake. How to achieve it, though? */
7
+ /* ~~~~~~~~~~~~~~~~ HPy ABI version ~~~~~~~~~~~~~~~ */
8
+ // NOTE: these must be kept on sync with the equivalent variables in hpy/devel/abitag.py
9
+ /**
10
+ * The ABI version.
11
+ *
12
+ * Minor version N+1 is binary compatible to minor version N. Major versions
13
+ * are not binary compatible (note: HPy can run several binary incompatible
14
+ * versions in one process).
15
+ */
16
+ #define HPY_ABI_VERSION 0
17
+ #define HPY_ABI_VERSION_MINOR 0
18
+ #define HPY_ABI_TAG "hpy0"
19
+
20
+
21
+ /* ~~~~~~~~~~~~~~~~ HPy ABI macros ~~~~~~~~~~~~~~~~ */
22
+
23
+ /* The following macros are used to determine which kind of module we want to
24
+ compile. The build system must set one of these (e.g. by using `gcc
25
+ -D...`). This is the approach used by the setuptools support provided by
26
+ hpy.devel:
27
+
28
+ - HPY_ABI_CPYTHON
29
+ - HPY_ABI_UNIVERSAL
30
+ - HPY_ABI_HYBRID
31
+
32
+ In addition we also define HPY_ABI which is a string literal containing a
33
+ string representation of it.
34
+ */
35
+
36
+ #if defined(HPY_ABI_CPYTHON )
37
+ # if defined(HPY_ABI_HYBRID )
38
+ # error "Conflicting macros are defined: HPY_ABI_CPYTHON and HPY_ABI_HYBRID"
39
+ # endif
40
+ # if defined(HPY_ABI_UNIVERSAL )
41
+ # error "Conflicting macros are defined: HPY_ABI_CPYTHON and HPY_ABI_UNIVERSAL"
42
+ # endif
43
+ # define HPY_ABI "cpython"
44
+
45
+ #elif defined(HPY_ABI_HYBRID )
46
+ # if defined(HPY_ABI_UNIVERSAL )
47
+ # error "Conflicting macros are defined: HPY_ABI_HYBRID and HPY_ABI_UNIVERSAL"
48
+ # endif
49
+ # define HPY_ABI "hybrid"
50
+
51
+ #elif defined(HPY_ABI_UNIVERSAL )
52
+ # define HPY_ABI "universal"
53
+
54
+ #else
55
+ # error "Cannot determine the desired HPy ABI: you must set one of HPY_ABI_CPYTHON, HPY_ABI_UNIVERSAL or HPY_ABI_HYBRID"
56
+ #endif
57
+
58
+
59
+ #if defined(HPY_ABI_CPYTHON ) || defined(HPY_ABI_HYBRID )
11
60
# define PY_SSIZE_T_CLEAN
12
61
# include <Python.h>
13
62
#endif
@@ -25,6 +74,7 @@ extern "C" {
25
74
# define _HPy_HIDDEN
26
75
# define _HPy_UNUSED
27
76
#endif /* __GNUC__ */
77
+ #define _HPy_UNUSED_ARG (x ) (__HPy_UNUSED_TAGGED ## x) _HPy_UNUSED
28
78
29
79
#if defined(__clang__ ) || \
30
80
(defined(__GNUC__ ) && \
@@ -37,6 +87,28 @@ extern "C" {
37
87
# define _HPy_NO_RETURN
38
88
#endif
39
89
90
+
91
+ // clang and gcc supports __has_attribute, MSVC doesn't. This should be enough
92
+ // to be able to use it portably
93
+ #ifdef __has_attribute
94
+ # define _HPY_compiler_has_attribute (x ) __has_attribute(x)
95
+ #else
96
+ # define _HPY_compiler_has_attribute (x ) 0
97
+ #endif
98
+
99
+ #ifdef HPY_ABI_UNIVERSAL
100
+ # if _HPY_compiler_has_attribute (error )
101
+ // gcc, clang>=14
102
+ # define _HPY_LEGACY __attribute__((error("Cannot use legacy functions when targeting the HPy Universal ABI")))
103
+ # else
104
+ // we don't have any diagnostic feature, too bad
105
+ # define _HPY_LEGACY
106
+ # endif
107
+ #else
108
+ // in non-universal modes, we don't attach any attribute
109
+ # define _HPY_LEGACY
110
+ #endif
111
+
40
112
#if defined(_MSC_VER ) && defined(__cplusplus ) // MSVC C4576
41
113
# define _hconv (h ) {h}
42
114
# define _hfconv (h ) {h}
@@ -67,6 +139,9 @@ extern "C" {
67
139
*/
68
140
#define HPyAPI_FUNC _HPy_UNUSED static inline
69
141
142
+ /** An alias for ``HPyAPI_FUNC`` so we can handle it properly in the docs. */
143
+ #define HPyAPI_INLINE_HELPER HPyAPI_FUNC
144
+
70
145
/**
71
146
* CPython implementations for ``HPyAPI_FUNC``
72
147
* functions. Generally speaking, they are put in ctx_*.c files and they are
@@ -104,7 +179,8 @@ extern "C" {
104
179
105
180
- PyPy: ._i is an index into a list
106
181
107
- - GraalPython: ???
182
+ - GraalPy: ._i is a tagged value, either an index into a list,
183
+ or an immediate integer or double value
108
184
109
185
- Debug mode: _i is a pointer to a DebugHandle, which contains a
110
186
another HPy among other stuff
@@ -123,15 +199,12 @@ typedef struct { intptr_t _i; } HPyThreadState;
123
199
#define HPy_NULL _hconv(0)
124
200
#define HPy_IsNull (h ) ((h)._i == 0)
125
201
126
- #define HPyListBuilder_IsNull (h ) ((h)._lst == 0)
127
- #define HPyTupleBuilder_IsNull (h ) ((h)._tup == 0)
128
-
129
202
#define HPyField_NULL _hfconv(0)
130
203
#define HPyField_IsNull (f ) ((f)._i == 0)
131
204
132
205
/* Convenience functions to cast between HPy and void*. We need to decide
133
206
whether these are part of the official API or not, and maybe introduce a
134
- better naming convetion . For now, they are needed for ujson. */
207
+ better naming convention . For now, they are needed for ujson. */
135
208
static inline HPy HPy_FromVoidP (void * p ) { return _hconv ((intptr_t )p ); }
136
209
static inline void * HPy_AsVoidP (HPy h ) { return (void * )h ._i ; }
137
210
@@ -140,51 +213,75 @@ static inline void* HPy_AsVoidP(HPy h) { return (void*)h._i; }
140
213
141
214
typedef struct _HPyContext_s HPyContext ;
142
215
143
- #ifdef HPY_UNIVERSAL_ABI
216
+ /** An enumeration of the different kinds of source code strings. */
217
+ typedef enum {
218
+ /** Parse isolated expressions (e.g. ``a + b``). */
219
+ HPy_SourceKind_Expr = 0 ,
220
+
221
+ /**
222
+ * Parse sequences of statements as read from a file or other source. This
223
+ * is the symbol to use when compiling arbitrarily long Python source code.
224
+ */
225
+ HPy_SourceKind_File = 1 ,
226
+
227
+ /**
228
+ * Parse a single statement. This is the mode used for the interactive
229
+ * interpreter loop.
230
+ */
231
+ HPy_SourceKind_Single = 2 ,
232
+ } HPy_SourceKind ;
233
+
234
+ #ifdef HPY_ABI_CPYTHON
235
+ typedef Py_ssize_t HPy_ssize_t ;
236
+ typedef Py_hash_t HPy_hash_t ;
237
+ typedef Py_UCS4 HPy_UCS4 ;
238
+
239
+ # define HPY_SSIZE_T_MAX PY_SSIZE_T_MAX
240
+ # define HPY_SSIZE_T_MIN PY_SSIZE_T_MIN
241
+
242
+ #else
144
243
typedef intptr_t HPy_ssize_t ;
145
244
typedef intptr_t HPy_hash_t ;
146
245
typedef uint32_t HPy_UCS4 ;
147
246
247
+ # define HPY_SSIZE_T_MAX INTPTR_MAX
248
+ # define HPY_SSIZE_T_MIN (-HPY_SSIZE_T_MAX-1)
249
+
148
250
/* HPyCapsule field keys */
149
251
typedef enum {
150
252
HPyCapsule_key_Pointer = 0 ,
151
253
HPyCapsule_key_Name = 1 ,
152
254
HPyCapsule_key_Context = 2 ,
153
255
HPyCapsule_key_Destructor = 3 ,
154
256
} _HPyCapsule_key ;
155
-
156
- #else
157
- typedef Py_ssize_t HPy_ssize_t ;
158
- typedef Py_hash_t HPy_hash_t ;
159
- typedef Py_UCS4 HPy_UCS4 ;
160
257
#endif
161
258
162
- typedef void (* HPyCapsule_Destructor )(const char * name , void * pointer , void * context );
163
-
164
259
165
260
/* ~~~~~~~~~~~~~~~~ Additional #includes ~~~~~~~~~~~~~~~~ */
166
261
167
262
#include "hpy/cpy_types.h"
263
+ #include "hpy/hpyexports.h"
168
264
#include "hpy/macros.h"
169
265
#include "hpy/hpyfunc.h"
170
266
#include "hpy/hpydef.h"
171
267
#include "hpy/hpytype.h"
172
268
#include "hpy/hpymodule.h"
173
269
#include "hpy/runtime/argparse.h"
174
270
#include "hpy/runtime/buildvalue.h"
271
+ #include "hpy/runtime/format.h"
175
272
#include "hpy/runtime/helpers.h"
176
273
#include "hpy/runtime/structseq.h"
177
274
178
- #ifdef HPY_UNIVERSAL_ABI
179
- # include "hpy/universal/autogen_ctx.h"
180
- # include "hpy/universal/autogen_trampolines.h"
181
- # include "hpy/universal/misc_trampolines.h"
182
- #else
183
- // CPython-ABI
275
+ #ifdef HPY_ABI_CPYTHON
276
+ # include "hpy/cpython/autogen_ctx.h"
184
277
# include "hpy/runtime/ctx_funcs.h"
185
278
# include "hpy/runtime/ctx_type.h"
186
279
# include "hpy/cpython/misc.h"
187
280
# include "hpy/cpython/autogen_api_impl.h"
281
+ #else
282
+ # include "hpy/universal/autogen_ctx.h"
283
+ # include "hpy/universal/autogen_trampolines.h"
284
+ # include "hpy/universal/misc_trampolines.h"
188
285
#endif
189
286
190
287
#include "hpy/inline_helpers.h"
0 commit comments