Skip to content

Commit eb07982

Browse files
authored
Merge pull request #147 from hpyproject/feature/add-hpy-call
Add HPy_CallTupleDict, HPyCallable_Check and HPyTuple_Check.
2 parents 656a623 + c520f3e commit eb07982

File tree

18 files changed

+322
-12
lines changed

18 files changed

+322
-12
lines changed

docs/porting-guide.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,24 @@ For lists of (say) integers::
4646
HPy h_list = HPyListBuilder_i_Build(ctx, builder);
4747

4848
And similar for building tuples or bytes
49+
50+
51+
PyObject_Call and PyObject_CallObject
52+
-------------------------------------
53+
54+
Both ``PyObject_Call`` and ``PyObject_CallObject`` are replaced by
55+
``HPy_CallTupleDict(callable, args, kwargs)`` in which either or both of
56+
``args`` and ``kwargs`` may be null handles.
57+
58+
``PyObject_Call(callable, args, kwargs)`` becomes:
59+
60+
HPy result = HPy_CallTupleDict(ctx, callable, args, kwargs);
61+
62+
``PyObject_CallObject(callable, args)`` becomes:
63+
64+
HPy result = HPy_CallTupleDict(ctx, callable, args, HPy_NULL);
65+
66+
If ``args`` is not a handle to a tuple or ``kwargs`` is not a handle to a
67+
dictionary, ``HPy_CallTupleDict`` will return ``HPy_NULL`` and raise a
68+
``TypeError``. This is different to ``PyObject_Call`` and
69+
``PyObject_CallObject`` which may segfault instead.

hpy/devel/include/common/autogen_impl.h

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef HPY_COMMON_RUNTIME_CALL_H
2+
#define HPY_COMMON_RUNTIME_CALL_H
3+
4+
#include <Python.h>
5+
#include "hpy.h"
6+
7+
_HPy_HIDDEN HPy
8+
ctx_CallTupleDict(HPyContext ctx, HPy callable, HPy args, HPy kw);
9+
10+
#endif /* HPY_COMMON_RUNTIME_CALL_H */

hpy/devel/include/cpython/hpy.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,7 @@ HPy_AsPyObject(HPyContext ctx, HPy h)
272272
#include "../common/hpydef.h"
273273
#include "../common/hpytype.h"
274274
#include "../common/hpymodule.h"
275+
#include "../common/runtime/ctx_call.h"
275276
#include "../common/runtime/ctx_module.h"
276277
#include "../common/runtime/ctx_type.h"
277278
#include "../common/runtime/ctx_listbuilder.h"
@@ -315,6 +316,12 @@ _HPy_Cast(HPyContext ctx, HPy h)
315316
return ctx_Cast(ctx, h);
316317
}
317318

319+
HPyAPI_FUNC(HPy)
320+
HPy_CallTupleDict(HPyContext ctx, HPy callable, HPy args, HPy kw)
321+
{
322+
return ctx_CallTupleDict(ctx, callable, args, kw);
323+
}
324+
318325
HPyAPI_FUNC(HPyListBuilder)
319326
HPyListBuilder_New(HPyContext ctx, HPy_ssize_t initial_size)
320327
{

hpy/devel/include/universal/autogen_ctx.h

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

hpy/devel/include/universal/autogen_trampolines.h

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

hpy/devel/src/runtime/ctx_call.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#include <Python.h>
2+
#include "hpy.h"
3+
4+
#ifdef HPY_UNIVERSAL_ABI
5+
// for _h2py and _py2h
6+
# include "handles.h"
7+
#endif
8+
9+
_HPy_HIDDEN HPy
10+
ctx_CallTupleDict(HPyContext ctx, HPy callable, HPy args, HPy kw)
11+
{
12+
PyObject *obj;
13+
if (!HPy_IsNull(args) && !HPyTuple_Check(ctx, args)) {
14+
HPyErr_SetString(ctx, ctx->h_TypeError,
15+
"HPy_CallTupleDict requires args to be a tuple or null handle");
16+
return HPy_NULL;
17+
}
18+
if (!HPy_IsNull(kw) && !HPyDict_Check(ctx, kw)) {
19+
HPyErr_SetString(ctx, ctx->h_TypeError,
20+
"HPy_CallTupleDict requires kw to be a dict or null handle");
21+
return HPy_NULL;
22+
}
23+
if (HPy_IsNull(kw)) {
24+
obj = PyObject_CallObject(_h2py(callable), _h2py(args));
25+
}
26+
else if (!HPy_IsNull(args)){
27+
obj = PyObject_Call(_h2py(callable), _h2py(args), _h2py(kw));
28+
}
29+
else {
30+
// args is null, but kw is not, so we need to create an empty args tuple
31+
// for CPython's PyObject_Call
32+
HPy items[] = {};
33+
HPy empty_tuple = HPyTuple_FromArray(ctx, items, 0);
34+
obj = PyObject_Call(_h2py(callable), _h2py(empty_tuple), _h2py(kw));
35+
HPy_Close(ctx, empty_tuple);
36+
}
37+
return _py2h(obj);
38+
}

hpy/tools/autogen/parse.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ def _visit_hpyslot_slot(self, node):
152152
'HPy_SetItem_i': None,
153153
'HPy_SetItem_s': None,
154154
'HPy_Length': 'PyObject_Length',
155-
'HPy_Call': 'PyObject_Call',
155+
'HPy_CallTupleDict': None,
156156
'_HPy_Cast': None,
157157
'HPy_FromPyObject': None,
158158
'HPy_AsPyObject': None,

hpy/tools/autogen/public_api.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,11 @@ HPy HPy_InPlaceAnd(HPyContext ctx, HPy h1, HPy h2);
164164
HPy HPy_InPlaceXor(HPyContext ctx, HPy h1, HPy h2);
165165
HPy HPy_InPlaceOr(HPyContext ctx, HPy h1, HPy h2);
166166

167+
int HPyCallable_Check(HPyContext ctx, HPy h);
168+
HPy HPy_CallTupleDict(HPyContext ctx, HPy callable, HPy args, HPy kw);
169+
167170
/* pyerrors.h */
171+
void HPy_FatalError(HPyContext ctx, const char *message);
168172
void HPyErr_SetString(HPyContext ctx, HPy h_type, const char *message);
169173
void HPyErr_SetObject(HPyContext ctx, HPy h_type, HPy h_value);
170174
/* note: HPyErr_Occurred() returns a flag 0-or-1, instead of a 'PyObject *' */
@@ -232,10 +236,8 @@ int HPyList_Append(HPyContext ctx, HPy h_list, HPy h_item);
232236
int HPyDict_Check(HPyContext ctx, HPy h);
233237
HPy HPyDict_New(HPyContext ctx);
234238

235-
/* pyerrors.h */
236-
void HPy_FatalError(HPyContext ctx, const char *message);
237-
238239
/* tupleobject.h */
240+
int HPyTuple_Check(HPyContext ctx, HPy h);
239241
HPy HPyTuple_FromArray(HPyContext ctx, HPy items[], HPy_ssize_t n);
240242
// note: HPyTuple_Pack is implemented as a macro in common/macros.h
241243

hpy/universal/src/autogen_ctx_def.h

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)