[pypy-commit] pypy hpy: update hpy_universal/_vendored to git revision 2129945

antocuni pypy.commits at gmail.com
Thu Nov 28 06:17:35 EST 2019


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: hpy
Changeset: r98165:988d96254bec
Date: 2019-11-28 01:20 +0100
http://bitbucket.org/pypy/pypy/changeset/988d96254bec/

Log:	update hpy_universal/_vendored to git revision 2129945

diff --git a/pypy/module/hpy_universal/_vendored/include/common/autogen_impl.h b/pypy/module/hpy_universal/_vendored/include/common/autogen_impl.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/hpy_universal/_vendored/include/common/autogen_impl.h
@@ -0,0 +1,110 @@
+
+/*
+   DO NOT EDIT THIS FILE!
+
+   This file is automatically generated by tools/autogen.py from tools/public_api.h.
+   Run this to regenerate:
+       make autogen
+
+*/
+
+HPyAPI_STORAGE HPy _HPy_IMPL_NAME(Long_FromLong)(HPyContext ctx, long value)
+{
+    return _py2h(PyLong_FromLong(value));
+}
+
+HPyAPI_STORAGE HPy _HPy_IMPL_NAME(Long_FromLongLong)(HPyContext ctx, long long v)
+{
+    return _py2h(PyLong_FromLongLong(v));
+}
+
+HPyAPI_STORAGE HPy _HPy_IMPL_NAME(Long_FromUnsignedLongLong)(HPyContext ctx, unsigned long long v)
+{
+    return _py2h(PyLong_FromUnsignedLongLong(v));
+}
+
+HPyAPI_STORAGE long _HPy_IMPL_NAME(Long_AsLong)(HPyContext ctx, HPy h)
+{
+    return PyLong_AsLong(_h2py(h));
+}
+
+HPyAPI_STORAGE HPy _HPy_IMPL_NAME(Float_FromDouble)(HPyContext ctx, double v)
+{
+    return _py2h(PyFloat_FromDouble(v));
+}
+
+HPyAPI_STORAGE HPy _HPy_IMPL_NAME(Number_Add)(HPyContext ctx, HPy x, HPy y)
+{
+    return _py2h(PyNumber_Add(_h2py(x), _h2py(y)));
+}
+
+HPyAPI_STORAGE void _HPy_IMPL_NAME(Err_SetString)(HPyContext ctx, HPy type, const char *message)
+{
+    return PyErr_SetString(_h2py(type), message);
+}
+
+HPyAPI_STORAGE int _HPy_IMPL_NAME(Bytes_Check)(HPyContext ctx, HPy o)
+{
+    return PyBytes_Check(_h2py(o));
+}
+
+HPyAPI_STORAGE HPy_ssize_t _HPy_IMPL_NAME(Bytes_Size)(HPyContext ctx, HPy o)
+{
+    return PyBytes_Size(_h2py(o));
+}
+
+HPyAPI_STORAGE HPy_ssize_t _HPy_IMPL_NAME(Bytes_GET_SIZE)(HPyContext ctx, HPy o)
+{
+    return PyBytes_GET_SIZE(_h2py(o));
+}
+
+HPyAPI_STORAGE char *_HPy_IMPL_NAME(Bytes_AsString)(HPyContext ctx, HPy o)
+{
+    return PyBytes_AsString(_h2py(o));
+}
+
+HPyAPI_STORAGE char *_HPy_IMPL_NAME(Bytes_AS_STRING)(HPyContext ctx, HPy o)
+{
+    return PyBytes_AS_STRING(_h2py(o));
+}
+
+HPyAPI_STORAGE HPy _HPy_IMPL_NAME(Unicode_FromString)(HPyContext ctx, const char *utf8)
+{
+    return _py2h(PyUnicode_FromString(utf8));
+}
+
+HPyAPI_STORAGE int _HPy_IMPL_NAME(Unicode_Check)(HPyContext ctx, HPy o)
+{
+    return PyUnicode_Check(_h2py(o));
+}
+
+HPyAPI_STORAGE HPy _HPy_IMPL_NAME(Unicode_AsUTF8String)(HPyContext ctx, HPy o)
+{
+    return _py2h(PyUnicode_AsUTF8String(_h2py(o)));
+}
+
+HPyAPI_STORAGE HPy _HPy_IMPL_NAME(Unicode_FromWideChar)(HPyContext ctx, const wchar_t *w, HPy_ssize_t size)
+{
+    return _py2h(PyUnicode_FromWideChar(w, size));
+}
+
+HPyAPI_STORAGE HPy _HPy_IMPL_NAME(List_New)(HPyContext ctx, HPy_ssize_t len)
+{
+    return _py2h(PyList_New(len));
+}
+
+HPyAPI_STORAGE int _HPy_IMPL_NAME(List_Append)(HPyContext ctx, HPy list, HPy item)
+{
+    return PyList_Append(_h2py(list), _h2py(item));
+}
+
+HPyAPI_STORAGE HPy _HPy_IMPL_NAME(Dict_New)(HPyContext ctx)
+{
+    return _py2h(PyDict_New());
+}
+
+HPyAPI_STORAGE int _HPy_IMPL_NAME(Dict_SetItem)(HPyContext ctx, HPy dict, HPy key, HPy val)
+{
+    return PyDict_SetItem(_h2py(dict), _h2py(key), _h2py(val));
+}
+
diff --git a/pypy/module/hpy_universal/_vendored/include/cpython/hpy.h b/pypy/module/hpy_universal/_vendored/include/cpython/hpy.h
--- a/pypy/module/hpy_universal/_vendored/include/cpython/hpy.h
+++ b/pypy/module/hpy_universal/_vendored/include/cpython/hpy.h
@@ -1,9 +1,6 @@
 #ifndef HPy_CPYTHON_H
 #define HPy_CPYTHON_H
 
-
-
-
 /* XXX: it would be nice if we could include hpy.h WITHOUT bringing in all the
    stuff from Python.h, to make sure that people don't use the CPython API by
    mistake. How to achieve it, though? Is defining Py_LIMITED_API enough? */
@@ -17,11 +14,12 @@
 #include <Python.h>
 
 #ifdef __GNUC__
-#define HPyAPI_FUNC(restype)  __attribute__((unused)) static inline restype
+#define HPyAPI_STORAGE __attribute__((unused)) static inline
 #else
-#define HPyAPI_FUNC(restype)  static inline restype
-#endif
+#define HPyAPI_STORAGE static inline
+#endif /* __GNUC__ */
 
+#define HPyAPI_FUNC(restype) HPyAPI_STORAGE restype
 
 typedef struct { PyObject *_o; } HPy;
 typedef Py_ssize_t HPy_ssize_t;
@@ -33,11 +31,14 @@
 #define _h2py(x) (x._o)
 #define _py2h(o) ((HPy){o})
 
+#include "meth.h"
+
 typedef struct _HPyContext_s {
     HPy h_None;
     HPy h_True;
     HPy h_False;
     HPy h_ValueError;
+    HPy h_TypeError;
 } *HPyContext;
 
 /* XXX! should be defined only once, not once for every .c! */
@@ -46,6 +47,13 @@
 #define HPy_NULL ((HPy){NULL})
 #define HPy_IsNull(x) ((x)._o == NULL)
 
+// XXX: we need to decide whether these are part of the official API or not,
+// and maybe introduce a better naming convetion. For now, they are needed for
+// ujson
+static inline HPy HPy_FromVoidP(void *p) { return (HPy){(PyObject*)p}; }
+static inline void* HPy_AsVoidP(HPy h) { return (void*)h._o; }
+
+
 HPyAPI_FUNC(HPyContext)
 _HPyGetContext(void) {
     HPyContext ctx = &_global_ctx;
@@ -56,19 +64,12 @@
         ctx->h_True = _py2h(Py_True);
         ctx->h_False = _py2h(Py_False);
         ctx->h_ValueError = _py2h(PyExc_ValueError);
+        ctx->h_TypeError = _py2h(PyExc_TypeError);
     }
     return ctx;
 }
 
 
-
-HPyAPI_FUNC(HPy)
-HPyNone_Get(HPyContext ctx)
-{
-    Py_INCREF(Py_None);
-    return _py2h(Py_None);
-}
-
 HPyAPI_FUNC(HPy)
 HPy_Dup(HPyContext ctx, HPy handle)
 {
@@ -84,6 +85,7 @@
 
 /* moduleobject.h */
 typedef PyModuleDef HPyModuleDef;
+
 #define HPyModuleDef_HEAD_INIT PyModuleDef_HEAD_INIT
 
 HPyAPI_FUNC(HPy)
@@ -99,37 +101,13 @@
         return _h2py(init_##modname##_impl(_HPyGetContext())); \
     }
 
-/* methodobject.h */
-typedef PyMethodDef HPyMethodDef;
-
-
-/* function declaration */
-
-#define HPy_METH_NOARGS(NAME)                                           \
-    static HPy NAME##_impl(HPyContext, HPy);                            \
-    static PyObject* NAME(PyObject *self, PyObject *noargs)             \
-    {                                                                   \
-        return _h2py(NAME##_impl(_HPyGetContext(), _py2h(self)));       \
-    }
-
-#define HPy_METH_O(NAME)                                                \
-    static HPy NAME##_impl(HPyContext, HPy, HPy);                       \
-    static PyObject* NAME(PyObject *self, PyObject *arg)                \
-    {                                                                   \
-        return _h2py(NAME##_impl(_HPyGetContext(), _py2h(self), _py2h(arg)));\
-    }
-
-#define HPy_METH_VARARGS(NAME)                                          \
-    static HPy NAME##_impl(HPyContext, HPy, HPy *, Py_ssize_t);         \
-    static PyObject* NAME(PyObject *self, PyObject *args)               \
-    {                                                                   \
-        /* get the tuple elements as an array of "PyObject *", which */ \
-        /* is equivalent to an array of "HPy" with enough casting... */ \
-        HPy *items = (HPy *)&PyTuple_GET_ITEM(args, 0);                 \
-        Py_ssize_t nargs = PyTuple_GET_SIZE(args);                      \
-        return _h2py(NAME##_impl(_HPyGetContext(), _py2h(self), items, nargs));\
-    }
-
+/* XXX: this function is copied&pasted THREE times:
+ *     hpy_devel/include/hpy.h
+ *     cpython-universal/api.c
+ *     pypy/module/hpy_universal/src/getargs.c
+ *
+ * We need a way to share this kind of common code
+ */
 
 HPyAPI_FUNC(int)
 HPyArg_Parse(HPyContext ctx, HPy *args, Py_ssize_t nargs, const char *fmt, ...)
@@ -166,30 +144,6 @@
 
 
 HPyAPI_FUNC(HPy)
-HPyLong_FromLong(HPyContext ctx, long v)
-{
-    return _py2h(PyLong_FromLong(v));
-}
-
-HPyAPI_FUNC(long)
-HPyLong_AsLong(HPyContext ctx, HPy h)
-{
-    return PyLong_AsLong(_h2py(h));
-}
-
-HPyAPI_FUNC(HPy)
-HPyNumber_Add(HPyContext ctx, HPy x, HPy y)
-{
-    return _py2h(PyNumber_Add(_h2py(x), _h2py(y)));
-}
-
-HPyAPI_FUNC(HPy)
-HPyUnicode_FromString(HPyContext ctx, const char *utf8)
-{
-    return _py2h(PyUnicode_FromString(utf8));
-}
-
-HPyAPI_FUNC(HPy)
 HPy_FromPyObject(HPyContext ctx, PyObject *obj)
 {
     Py_XINCREF(obj);
@@ -204,11 +158,12 @@
     return result;
 }
 
-HPyAPI_FUNC(void)
-HPyErr_SetString(HPyContext ctx, HPy type, const char *message)
-{
-    PyErr_SetString(_h2py(type), message);
-}
-
+/* expand impl functions as:
+ *     static inline HPyLong_FromLong(...);
+ *
+ */
+#define _HPy_IMPL_NAME(name) HPy##name
+#include "../common/autogen_impl.h"
+#undef _HPy_IMPL_NAME
 
 #endif /* !HPy_CPYTHON_H */
diff --git a/pypy/module/hpy_universal/_vendored/include/cpython/meth.h b/pypy/module/hpy_universal/_vendored/include/cpython/meth.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/hpy_universal/_vendored/include/cpython/meth.h
@@ -0,0 +1,50 @@
+#ifndef HPY_CPYTHON_METH_H
+#define HPY_CPYTHON_METH_H
+
+typedef PyMethodDef HPyMethodDef;
+
+// this is the type of the field HPyMethodDef.ml_meth: cast to it to silence
+// warnings
+typedef PyCFunction HPyMeth;
+
+// XXX: we need to find a way to let the user declare things as static if
+// he/she wants
+
+/* METH declaration */
+#define HPy_DECL_METH_NOARGS(NAME) PyObject* NAME(PyObject *, PyObject *);
+#define HPy_DECL_METH_O(NAME) HPy_DECL_METH_NOARGS(NAME)
+#define HPy_DECL_METH_VARARGS(NAME) HPy_DECL_METH_NOARGS(NAME)
+
+/* METH definition */
+#define HPy_DEF_METH_NOARGS(NAME)                                       \
+    static HPy NAME##_impl(HPyContext, HPy);                            \
+    PyObject* NAME(PyObject *self, PyObject *noargs)                    \
+    {                                                                   \
+        return _h2py(NAME##_impl(_HPyGetContext(), _py2h(self)));       \
+    }
+
+#define HPy_DEF_METH_O(NAME)                                            \
+    static HPy NAME##_impl(HPyContext, HPy, HPy);                       \
+    PyObject* NAME(PyObject *self, PyObject *arg)                       \
+    {                                                                   \
+        return _h2py(NAME##_impl(_HPyGetContext(), _py2h(self), _py2h(arg)));\
+    }
+
+#define HPy_DEF_METH_VARARGS(NAME)                                      \
+    static HPy NAME##_impl(HPyContext, HPy, HPy *, Py_ssize_t);         \
+    PyObject* NAME(PyObject *self, PyObject *args)                      \
+    {                                                                   \
+        /* get the tuple elements as an array of "PyObject *", which */ \
+        /* is equivalent to an array of "HPy" with enough casting... */ \
+        HPy *items = (HPy *)&PyTuple_GET_ITEM(args, 0);                 \
+        Py_ssize_t nargs = PyTuple_GET_SIZE(args);                      \
+        return _h2py(NAME##_impl(_HPyGetContext(), _py2h(self), items, nargs));\
+    }
+
+#define HPy_METH_NOARGS METH_NOARGS
+#define HPy_METH_O METH_O
+#define HPy_METH_VARARGS METH_VARARGS
+
+
+
+#endif // HPY_CPYTHON_METH_H
diff --git a/pypy/module/hpy_universal/_vendored/include/universal/autogen_ctx.h b/pypy/module/hpy_universal/_vendored/include/universal/autogen_ctx.h
--- a/pypy/module/hpy_universal/_vendored/include/universal/autogen_ctx.h
+++ b/pypy/module/hpy_universal/_vendored/include/universal/autogen_ctx.h
@@ -14,15 +14,31 @@
     HPy h_True;
     HPy h_False;
     HPy h_ValueError;
+    HPy h_TypeError;
     HPy (*ctx_Module_Create)(HPyContext ctx, HPyModuleDef *def);
     HPy (*ctx_Dup)(HPyContext ctx, HPy h);
     void (*ctx_Close)(HPyContext ctx, HPy h);
     HPy (*ctx_Long_FromLong)(HPyContext ctx, long value);
+    HPy (*ctx_Long_FromLongLong)(HPyContext ctx, long long v);
+    HPy (*ctx_Long_FromUnsignedLongLong)(HPyContext ctx, unsigned long long v);
     long (*ctx_Long_AsLong)(HPyContext ctx, HPy h);
+    HPy (*ctx_Float_FromDouble)(HPyContext ctx, double v);
     int (*ctx_Arg_Parse)(HPyContext ctx, HPy *args, HPy_ssize_t nargs, const char *fmt, va_list _vl);
     HPy (*ctx_Number_Add)(HPyContext ctx, HPy x, HPy y);
+    void (*ctx_Err_SetString)(HPyContext ctx, HPy type, const char *message);
+    int (*ctx_Bytes_Check)(HPyContext ctx, HPy o);
+    HPy_ssize_t (*ctx_Bytes_Size)(HPyContext ctx, HPy o);
+    HPy_ssize_t (*ctx_Bytes_GET_SIZE)(HPyContext ctx, HPy o);
+    char *(*ctx_Bytes_AsString)(HPyContext ctx, HPy o);
+    char *(*ctx_Bytes_AS_STRING)(HPyContext ctx, HPy o);
     HPy (*ctx_Unicode_FromString)(HPyContext ctx, const char *utf8);
-    void (*ctx_Err_SetString)(HPyContext ctx, HPy type, const char *message);
+    int (*ctx_Unicode_Check)(HPyContext ctx, HPy o);
+    HPy (*ctx_Unicode_AsUTF8String)(HPyContext ctx, HPy o);
+    HPy (*ctx_Unicode_FromWideChar)(HPyContext ctx, const wchar_t *w, HPy_ssize_t size);
+    HPy (*ctx_List_New)(HPyContext ctx, HPy_ssize_t len);
+    int (*ctx_List_Append)(HPyContext ctx, HPy list, HPy item);
+    HPy (*ctx_Dict_New)(HPyContext ctx);
+    int (*ctx_Dict_SetItem)(HPyContext ctx, HPy dict, HPy key, HPy val);
     HPy (*ctx_FromPyObject)(HPyContext ctx, struct _object *obj);
     struct _object *(*ctx_AsPyObject)(HPyContext ctx, HPy h);
     struct _object *(*ctx_CallRealFunctionFromTrampoline)(HPyContext ctx, struct _object *self, struct _object *args, void *func, int ml_flags);
diff --git a/pypy/module/hpy_universal/_vendored/include/universal/autogen_trampolines.h b/pypy/module/hpy_universal/_vendored/include/universal/autogen_trampolines.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/hpy_universal/_vendored/include/universal/autogen_trampolines.h
@@ -0,0 +1,118 @@
+
+/*
+   DO NOT EDIT THIS FILE!
+
+   This file is automatically generated by tools/autogen.py from tools/public_api.h.
+   Run this to regenerate:
+       make autogen
+
+*/
+
+static inline HPy HPyModule_Create(HPyContext ctx, HPyModuleDef *def) {
+     return ctx->ctx_Module_Create ( ctx, def ); 
+}
+
+static inline HPy HPy_Dup(HPyContext ctx, HPy h) {
+     return ctx->ctx_Dup ( ctx, h ); 
+}
+
+static inline void HPy_Close(HPyContext ctx, HPy h) {
+     ctx->ctx_Close ( ctx, h ); 
+}
+
+static inline HPy HPyLong_FromLong(HPyContext ctx, long value) {
+     return ctx->ctx_Long_FromLong ( ctx, value ); 
+}
+
+static inline HPy HPyLong_FromLongLong(HPyContext ctx, long long v) {
+     return ctx->ctx_Long_FromLongLong ( ctx, v ); 
+}
+
+static inline HPy HPyLong_FromUnsignedLongLong(HPyContext ctx, unsigned long long v) {
+     return ctx->ctx_Long_FromUnsignedLongLong ( ctx, v ); 
+}
+
+static inline long HPyLong_AsLong(HPyContext ctx, HPy h) {
+     return ctx->ctx_Long_AsLong ( ctx, h ); 
+}
+
+static inline HPy HPyFloat_FromDouble(HPyContext ctx, double v) {
+     return ctx->ctx_Float_FromDouble ( ctx, v ); 
+}
+
+static inline int HPyArg_Parse(HPyContext ctx, HPy *args, HPy_ssize_t nargs, const char *fmt, ...) {
+     va_list _vl; va_start(_vl, fmt); int _res = ctx->ctx_Arg_Parse ( ctx, args, nargs, fmt, _vl ); va_end(_vl); return _res; 
+}
+
+static inline HPy HPyNumber_Add(HPyContext ctx, HPy x, HPy y) {
+     return ctx->ctx_Number_Add ( ctx, x, y ); 
+}
+
+static inline void HPyErr_SetString(HPyContext ctx, HPy type, const char *message) {
+     ctx->ctx_Err_SetString ( ctx, type, message ); 
+}
+
+static inline int HPyBytes_Check(HPyContext ctx, HPy o) {
+     return ctx->ctx_Bytes_Check ( ctx, o ); 
+}
+
+static inline HPy_ssize_t HPyBytes_Size(HPyContext ctx, HPy o) {
+     return ctx->ctx_Bytes_Size ( ctx, o ); 
+}
+
+static inline HPy_ssize_t HPyBytes_GET_SIZE(HPyContext ctx, HPy o) {
+     return ctx->ctx_Bytes_GET_SIZE ( ctx, o ); 
+}
+
+static inline char *HPyBytes_AsString(HPyContext ctx, HPy o) {
+     return ctx->ctx_Bytes_AsString ( ctx, o ); 
+}
+
+static inline char *HPyBytes_AS_STRING(HPyContext ctx, HPy o) {
+     return ctx->ctx_Bytes_AS_STRING ( ctx, o ); 
+}
+
+static inline HPy HPyUnicode_FromString(HPyContext ctx, const char *utf8) {
+     return ctx->ctx_Unicode_FromString ( ctx, utf8 ); 
+}
+
+static inline int HPyUnicode_Check(HPyContext ctx, HPy o) {
+     return ctx->ctx_Unicode_Check ( ctx, o ); 
+}
+
+static inline HPy HPyUnicode_AsUTF8String(HPyContext ctx, HPy o) {
+     return ctx->ctx_Unicode_AsUTF8String ( ctx, o ); 
+}
+
+static inline HPy HPyUnicode_FromWideChar(HPyContext ctx, const wchar_t *w, HPy_ssize_t size) {
+     return ctx->ctx_Unicode_FromWideChar ( ctx, w, size ); 
+}
+
+static inline HPy HPyList_New(HPyContext ctx, HPy_ssize_t len) {
+     return ctx->ctx_List_New ( ctx, len ); 
+}
+
+static inline int HPyList_Append(HPyContext ctx, HPy list, HPy item) {
+     return ctx->ctx_List_Append ( ctx, list, item ); 
+}
+
+static inline HPy HPyDict_New(HPyContext ctx) {
+     return ctx->ctx_Dict_New ( ctx ); 
+}
+
+static inline int HPyDict_SetItem(HPyContext ctx, HPy dict, HPy key, HPy val) {
+     return ctx->ctx_Dict_SetItem ( ctx, dict, key, val ); 
+}
+
+static inline HPy HPy_FromPyObject(HPyContext ctx, struct _object *obj) {
+     return ctx->ctx_FromPyObject ( ctx, obj ); 
+}
+
+static inline struct _object *HPy_AsPyObject(HPyContext ctx, HPy h) {
+     return ctx->ctx_AsPyObject ( ctx, h ); 
+}
+
+static inline struct _object *_HPy_CallRealFunctionFromTrampoline(HPyContext ctx, struct _object *self, struct _object *args, void *func, int ml_flags) {
+     return ctx->ctx_CallRealFunctionFromTrampoline ( ctx, self, args, func, ml_flags ); 
+}
+
diff --git a/pypy/module/hpy_universal/_vendored/include/universal/hpy.h b/pypy/module/hpy_universal/_vendored/include/universal/hpy.h
--- a/pypy/module/hpy_universal/_vendored/include/universal/hpy.h
+++ b/pypy/module/hpy_universal/_vendored/include/universal/hpy.h
@@ -1,113 +1,33 @@
-#ifndef HPy_UNIVERSAL_H
-#define HPy_UNIVERSAL_H
+#ifndef HPY_UNIVERSAL_H
+#define HPY_UNIVERSAL_H
 
 #include <stdlib.h>
 #include <stdint.h>
 #include <stdarg.h>
 
 typedef intptr_t HPy_ssize_t;
-
-// WARNING: the following change has been done inside the pypy hpy-ctypespace
-// branch. If/when the branch is merged, we should backport it to pyhandle/hpy
-struct _HPy_s { HPy_ssize_t _i; };
-typedef struct _HPy_s HPy;
+typedef struct { HPy_ssize_t _i; } HPy;
 
 typedef struct _HPyContext_s *HPyContext;
 struct _object;  /* that's PyObject inside CPython */
 typedef struct _object *(*_HPy_CPyCFunction)(struct _object *self,
                                              struct _object *args);
 
+#define _HPy_HIDDEN   __attribute__((visibility("hidden")))
 #define HPy_NULL ((HPy){0})
 #define HPy_IsNull(x) ((x)._i == 0)
 
-typedef void (*_HPyMethodPairFunc)(void **out_func,
-                                   _HPy_CPyCFunction *out_trampoline);
+// XXX: we need to decide whether these are part of the official API or not,
+// and maybe introduce a better naming convetion. For now, they are needed for
+// ujson
+static inline HPy HPy_FromVoidP(void *p) { return (HPy){(HPy_ssize_t)p}; }
+static inline void* HPy_AsVoidP(HPy h) { return (void*)h._i; }
 
-typedef struct {
-    const char   *ml_name;   /* The name of the built-in function/method */
-    _HPyMethodPairFunc ml_meth;   /* see HPy_FUNCTION() */
-    int          ml_flags;   /* Combination of METH_xxx flags, which mostly
-                                describe the args expected by the C func */
-    const char   *ml_doc;    /* The __doc__ attribute, or NULL */
-} HPyMethodDef;
 
-
-#define HPyModuleDef_HEAD_INIT NULL
-
-typedef struct {
-    void *dummy; // this is needed because we put a comma after HPyModuleDef_HEAD_INIT :(
-    const char* m_name;
-    const char* m_doc;
-    HPy_ssize_t m_size;
-    HPyMethodDef *m_methods;
-} HPyModuleDef;
-
-#define _HPy_HIDDEN   __attribute__((visibility("hidden")))
-#define HPy_MODINIT(modname)                                   \
-    _HPy_HIDDEN HPyContext _ctx_for_trampolines;               \
-    static HPy init_##modname##_impl(HPyContext ctx);          \
-    HPy HPyInit_##modname(HPyContext ctx)                      \
-    {                                                          \
-        _ctx_for_trampolines = ctx;                            \
-        return init_##modname##_impl(ctx);                     \
-    }
+#include "meth.h"
+#include "module.h"
 
 #include "autogen_ctx.h"
-#include "autogen_func.h"
+#include "autogen_trampolines.h"
 
-extern HPyContext _ctx_for_trampolines;
-
-
-#define HPy_METH_NOARGS(fnname)                                                \
-    static HPy fnname##_impl(HPyContext ctx, HPy self);                        \
-    static struct _object *                                                    \
-    fnname##_trampoline(struct _object *self, struct _object *noargs)          \
-    {                                                                          \
-        return _HPy_CallRealFunctionFromTrampoline(                            \
-            _ctx_for_trampolines, self, NULL, fnname##_impl, METH_NOARGS);     \
-    }                                                                          \
-    static void                                                                \
-    fnname(void **out_func, _HPy_CPyCFunction *out_trampoline)                 \
-    {                                                                          \
-        *out_func = fnname##_impl;                                             \
-        *out_trampoline = fnname##_trampoline;                                 \
-    }
-
-#define HPy_METH_O(fnname)                                                     \
-    static HPy fnname##_impl(HPyContext ctx, HPy self, HPy arg);               \
-    static struct _object *                                                    \
-    fnname##_trampoline(struct _object *self, struct _object *arg)             \
-    {                                                                          \
-        return _HPy_CallRealFunctionFromTrampoline(                            \
-            _ctx_for_trampolines, self, arg, fnname##_impl, METH_O);           \
-    }                                                                          \
-    static void                                                                \
-    fnname(void **out_func, _HPy_CPyCFunction *out_trampoline)                 \
-    {                                                                          \
-        *out_func = fnname##_impl;                                             \
-        *out_trampoline = fnname##_trampoline;                                 \
-    }
-
-#define HPy_METH_VARARGS(fnname)                                               \
-    static HPy fnname##_impl(HPyContext ctx, HPy self, HPy *args, HPy_ssize_t);\
-    static struct _object *                                                    \
-    fnname##_trampoline(struct _object *self, struct _object *args)            \
-    {                                                                          \
-        return _HPy_CallRealFunctionFromTrampoline(                            \
-            _ctx_for_trampolines, self, args, fnname##_impl, METH_VARARGS);    \
-    }                                                                          \
-    static void                                                                \
-    fnname(void **out_func, _HPy_CPyCFunction *out_trampoline)                 \
-    {                                                                          \
-        *out_func = fnname##_impl;                                             \
-        *out_trampoline = fnname##_trampoline;                                 \
-    }
-
-#define METH_VARARGS  0x0001
-#define METH_KEYWORDS 0x0002
-/* METH_NOARGS and METH_O must not be combined with the flags above. */
-#define METH_NOARGS   0x0004
-#define METH_O        0x0008
-
-
-#endif /* HPy_UNIVERSAL_H */
+#endif /* HPY_UNIVERSAL_H */
diff --git a/pypy/module/hpy_universal/_vendored/include/universal/meth.h b/pypy/module/hpy_universal/_vendored/include/universal/meth.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/hpy_universal/_vendored/include/universal/meth.h
@@ -0,0 +1,95 @@
+#ifndef HPY_UNIVERSAL_METH_H
+#define HPY_UNIVERSAL_METH_H
+
+/* in universal mode, an HPyMeth is a function which returns two output
+ * arguments:
+ *
+ *     - the *_impl function
+ *     - a trampoline which can be called by CPython
+ *
+ * In theory, the CPython trampoline is an implementation-specific detail of
+ * the hpy_universal CPython module. However, it is too hard and unreliable to
+ * generate them on the fly, and for the sake of simplicity it is easier to
+ * just let the C compiler to generate it. This is done by the DEF macros.
+ */
+typedef void (*HPyMeth)(void **out_func, _HPy_CPyCFunction *out_trampoline);
+
+/* ml_flags can be:
+ *
+ *   - METH_NOARGS, METH_O, etc: in this case ml_meth is interpreted as a legacy
+ *     CPython function
+ *
+ *   - HPy_METH_NOARGS, etc: in this case ml_meth is interpreted as a new-style
+ *     HPy function
+ */
+typedef struct {
+    const char   *ml_name;   /* The name of the built-in function/method */
+    HPyMeth      ml_meth;    /* see HPy_DEF_METH_*() */
+    int          ml_flags;   /* Combination of METH_xxx flags, which mostly
+                                describe the args expected by the C func */
+    const char   *ml_doc;    /* The __doc__ attribute, or NULL */
+} HPyMethodDef;
+
+#define HPy_DECL_METH_NOARGS(fnname)                                    \
+    void fnname(void **out_func, _HPy_CPyCFunction *out_trampoline);
+
+#define HPy_DECL_METH_O(NAME) HPy_DECL_METH_NOARGS(NAME)
+#define HPy_DECL_METH_VARARGS(NAME) HPy_DECL_METH_NOARGS(NAME)
+
+
+#define HPy_DEF_METH_NOARGS(fnname)                                            \
+    static HPy fnname##_impl(HPyContext ctx, HPy self);                        \
+    static struct _object *                                                    \
+    fnname##_trampoline(struct _object *self, struct _object *noargs)          \
+    {                                                                          \
+        return _HPy_CallRealFunctionFromTrampoline(                            \
+            _ctx_for_trampolines, self, NULL, fnname##_impl, HPy_METH_NOARGS); \
+    }                                                                          \
+    void                                                                       \
+    fnname(void **out_func, _HPy_CPyCFunction *out_trampoline)                 \
+    {                                                                          \
+        *out_func = fnname##_impl;                                             \
+        *out_trampoline = fnname##_trampoline;                                 \
+    }
+
+#define HPy_DEF_METH_O(fnname)                                                 \
+    static HPy fnname##_impl(HPyContext ctx, HPy self, HPy arg);               \
+    static struct _object *                                                    \
+    fnname##_trampoline(struct _object *self, struct _object *arg)             \
+    {                                                                          \
+        return _HPy_CallRealFunctionFromTrampoline(                            \
+            _ctx_for_trampolines, self, arg, fnname##_impl, HPy_METH_O);       \
+    }                                                                          \
+    void                                                                       \
+    fnname(void **out_func, _HPy_CPyCFunction *out_trampoline)                 \
+    {                                                                          \
+        *out_func = fnname##_impl;                                             \
+        *out_trampoline = fnname##_trampoline;                                 \
+    }
+
+#define HPy_DEF_METH_VARARGS(fnname)                                           \
+    static HPy fnname##_impl(HPyContext ctx, HPy self, HPy *args, HPy_ssize_t);\
+    static struct _object *                                                    \
+    fnname##_trampoline(struct _object *self, struct _object *args)            \
+    {                                                                          \
+        return _HPy_CallRealFunctionFromTrampoline(                            \
+            _ctx_for_trampolines, self, args, fnname##_impl, HPy_METH_VARARGS);\
+    }                                                                          \
+    void                                                                       \
+    fnname(void **out_func, _HPy_CPyCFunction *out_trampoline)                 \
+    {                                                                          \
+        *out_func = fnname##_impl;                                             \
+        *out_trampoline = fnname##_trampoline;                                 \
+    }
+
+
+// make sure to use a bit which is unused by CPython
+#define _HPy_METH 0x100000
+#define HPy_METH_VARARGS  (0x0001 | _HPy_METH)
+#define HPy_METH_KEYWORDS (0x0002 | _HPy_METH)
+/* METH_NOARGS and METH_O must not be combined with the flags above. */
+#define HPy_METH_NOARGS   (0x0004 | _HPy_METH)
+#define HPy_METH_O        (0x0008 | _HPy_METH)
+
+
+#endif // HPY_UNIVERSAL_METH_H
diff --git a/pypy/module/hpy_universal/_vendored/include/universal/module.h b/pypy/module/hpy_universal/_vendored/include/universal/module.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/hpy_universal/_vendored/include/universal/module.h
@@ -0,0 +1,27 @@
+#ifndef HPY_UNIVERSAL_MODULE_H
+#define HPY_UNIVERSAL_MODULE_H
+
+// this is defined by HPy_MODINIT
+extern HPyContext _ctx_for_trampolines;
+
+#define HPyModuleDef_HEAD_INIT NULL
+
+typedef struct {
+    void *dummy; // this is needed because we put a comma after HPyModuleDef_HEAD_INIT :(
+    const char* m_name;
+    const char* m_doc;
+    HPy_ssize_t m_size;
+    HPyMethodDef *m_methods;
+} HPyModuleDef;
+
+
+#define HPy_MODINIT(modname)                                   \
+    _HPy_HIDDEN HPyContext _ctx_for_trampolines;               \
+    static HPy init_##modname##_impl(HPyContext ctx);          \
+    HPy HPyInit_##modname(HPyContext ctx)                      \
+    {                                                          \
+        _ctx_for_trampolines = ctx;                            \
+        return init_##modname##_impl(ctx);                     \
+    }
+
+#endif // HPY_UNIVERSAL_MODULE_H
diff --git a/pypy/module/hpy_universal/_vendored/test/conftest.py b/pypy/module/hpy_universal/_vendored/test/conftest.py
--- a/pypy/module/hpy_universal/_vendored/test/conftest.py
+++ b/pypy/module/hpy_universal/_vendored/test/conftest.py
@@ -6,6 +6,10 @@
         "--correct", action="store_true",
         help="Test against headers installed through hpy_devel"
     )
+    parser.addoption(
+        "--compiler-v", action="store_true",
+        help="Print to stdout the commands used to invoke the compiler")
+
 
 @pytest.fixture(scope='session')
 def hpy_include_dir(request):
@@ -22,5 +26,7 @@
     return request.param
 
 @pytest.fixture
-def compiler(tmpdir, abimode, hpy_include_dir):
-    return ExtensionCompiler(tmpdir, abimode, hpy_include_dir)
+def compiler(request, tmpdir, abimode, hpy_include_dir):
+    compiler_verbose = request.config.getoption('--compiler-v')
+    return ExtensionCompiler(tmpdir, abimode, hpy_include_dir,
+                             compiler_verbose=compiler_verbose)
diff --git a/pypy/module/hpy_universal/_vendored/test/support.py b/pypy/module/hpy_universal/_vendored/test/support.py
--- a/pypy/module/hpy_universal/_vendored/test/support.py
+++ b/pypy/module/hpy_universal/_vendored/test/support.py
@@ -3,7 +3,7 @@
 import re
 
 r_marker_init = re.compile(r"\s*@INIT\s*$")
-r_marker_export = re.compile(r"\s*@EXPORT\s+(\w+)\s+(METH_\w+)\s*$")
+r_marker_export = re.compile(r"\s*@EXPORT\s+(\w+)\s+(.*)\s*$")
 
 INIT_TEMPLATE = """
 static HPyMethodDef MyTestMethods[] = {
@@ -47,8 +47,14 @@
         match = r_marker_export.match(line)
         if match:
             ml_name, ml_flags = match.group(1), match.group(2)
-            method_table.append('{"%s", %s, %s, NULL},' % (
-                ml_name, ml_name, ml_flags))
+            if not ml_flags.startswith('HPy_'):
+                # this is a legacy function: add a cast to (HPyMeth) to
+                # silence warnings
+                cast = '(HPyMeth)'
+            else:
+                cast = ''
+            method_table.append('{"%s", %s%s, %s, NULL},' % (
+                    ml_name, cast, ml_name, ml_flags))
             continue
 
         expanded_lines.append(line)
@@ -62,34 +68,45 @@
 
 
 class ExtensionCompiler:
-    def __init__(self, tmpdir, abimode, include_dir):
+    def __init__(self, tmpdir, abimode, include_dir, compiler_verbose=False):
         self.tmpdir = tmpdir
         self.abimode = abimode
         self.include_dir = include_dir
         self.universal_mode = self.abimode == 'universal'
+        self.compiler_verbose = compiler_verbose
 
-    def compile_module(self, source_template, name):
+    def _expand(self, name, template):
+        source = expand_template(template, name)
+        filename = self.tmpdir.join(name + '.c')
+        filename.write(source)
+        return filename
+
+    def compile_module(self, main_template, name, extra_templates):
         """
         Create and compile a HPy module from the template
         """
-        source = expand_template(source_template, name)
-        filename = self.tmpdir.join(name + '.c')
-        filename.write(source)
+        filename = self._expand(name, main_template)
+        sources = []
+        for i, template in enumerate(extra_templates):
+            extra_filename = self._expand('extmod_%d' % i, template)
+            sources.append(extra_filename)
         #
         ext = get_extension(str(filename), name,
+                            sources=sources,
                             include_dirs=[self.include_dir],
                             extra_compile_args=['-Wfatal-errors', '-g', '-Og'],
                             extra_link_args=['-g'])
-        so_filename = c_compile(str(self.tmpdir), ext, compiler_verbose=False,
+        so_filename = c_compile(str(self.tmpdir), ext,
+                                compiler_verbose=self.compiler_verbose,
                                 universal_mode=self.universal_mode)
         return so_filename
 
-    def make_module(self, source_template, name):
+    def make_module(self, main_template, name, extra_templates):
         """
         Compile&load a modulo into memory. This is NOT a proper import: e.g. the module
         is not put into sys.modules
         """
-        so_filename = self.compile_module(source_template, name)
+        so_filename = self.compile_module(main_template, name, extra_templates)
         if self.universal_mode:
             return self.load_universal_module(name, so_filename)
         else:
@@ -122,11 +139,8 @@
         # compiler is a fixture defined in conftest
         self.compiler = compiler
 
-    def compile_module(self, source_template, name):
-        return self.compiler.compile_module(source_template, name)
-
-    def make_module(self, source_template, name='mytest'):
-        return self.compiler.make_module(source_template, name)
+    def make_module(self, source_template, name='mytest', extra_templates=()):
+        return self.compiler.make_module(source_template, name, extra_templates)
 
 
 # the few functions below are copied and adapted from cffi/ffiplatform.py
diff --git a/pypy/module/hpy_universal/_vendored/test/test_basic.py b/pypy/module/hpy_universal/_vendored/test/test_basic.py
--- a/pypy/module/hpy_universal/_vendored/test/test_basic.py
+++ b/pypy/module/hpy_universal/_vendored/test/test_basic.py
@@ -26,36 +26,36 @@
 
     def test_noop_function(self):
         mod = self.make_module("""
-            HPy_METH_NOARGS(f)
+            HPy_DEF_METH_NOARGS(f)
             static HPy f_impl(HPyContext ctx, HPy self)
             {
                 return HPy_Dup(ctx, ctx->h_None);
             }
-            @EXPORT f METH_NOARGS
+            @EXPORT f HPy_METH_NOARGS
             @INIT
         """)
         assert mod.f() is None
 
     def test_self_is_module(self):
         mod = self.make_module("""
-            HPy_METH_NOARGS(f)
+            HPy_DEF_METH_NOARGS(f)
             static HPy f_impl(HPyContext ctx, HPy self)
             {
                 return HPy_Dup(ctx, self);
             }
-            @EXPORT f METH_NOARGS
+            @EXPORT f HPy_METH_NOARGS
             @INIT
         """)
         assert mod.f() is mod
 
     def test_identity_function(self):
         mod = self.make_module("""
-            HPy_METH_O(f)
+            HPy_DEF_METH_O(f)
             static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
             {
                 return HPy_Dup(ctx, arg);
             }
-            @EXPORT f METH_O
+            @EXPORT f HPy_METH_O
             @INIT
         """)
         x = object()
@@ -63,13 +63,13 @@
 
     def test_long_aslong(self):
         mod = self.make_module("""
-            HPy_METH_O(f)
+            HPy_DEF_METH_O(f)
             static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
             {
                 long a = HPyLong_AsLong(ctx, arg);
                 return HPyLong_FromLong(ctx, a * 2);
             }
-            @EXPORT f METH_O
+            @EXPORT f HPy_METH_O
             @INIT
         """)
         assert mod.f(45) == 90
@@ -77,18 +77,18 @@
     def test_wrong_number_of_arguments(self):
         import pytest
         mod = self.make_module("""
-            HPy_METH_NOARGS(f_noargs)
+            HPy_DEF_METH_NOARGS(f_noargs)
             static HPy f_noargs_impl(HPyContext ctx, HPy self)
             {
                 return HPy_Dup(ctx, ctx->h_None);
             }
-            HPy_METH_O(f_o)
+            HPy_DEF_METH_O(f_o)
             static HPy f_o_impl(HPyContext ctx, HPy self, HPy arg)
             {
                 return HPy_Dup(ctx, ctx->h_None);
             }
-            @EXPORT f_noargs METH_NOARGS
-            @EXPORT f_o METH_O
+            @EXPORT f_noargs HPy_METH_NOARGS
+            @EXPORT f_o HPy_METH_O
             @INIT
         """)
         with pytest.raises(TypeError):
@@ -100,7 +100,7 @@
 
     def test_many_int_arguments(self):
         mod = self.make_module("""
-            HPy_METH_VARARGS(f)
+            HPy_DEF_METH_VARARGS(f)
             static HPy f_impl(HPyContext ctx, HPy self,
                               HPy *args, HPy_ssize_t nargs)
             {
@@ -111,14 +111,14 @@
                 return HPyLong_FromLong(ctx,
                     10000*a + 1000*b + 100*c + 10*d + e);
             }
-            @EXPORT f METH_VARARGS
+            @EXPORT f HPy_METH_VARARGS
             @INIT
         """)
         assert mod.f(4, 5, 6, 7, 8) == 45678
 
     def test_close(self):
         mod = self.make_module("""
-            HPy_METH_O(f)
+            HPy_DEF_METH_O(f)
             static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
             {
                 HPy one = HPyLong_FromLong(ctx, 1);
@@ -128,32 +128,20 @@
                 HPy_Close(ctx, one);
                 return res;
             }
-            @EXPORT f METH_O
+            @EXPORT f HPy_METH_O
             @INIT
         """)
         assert mod.f(41.5) == 42.5
 
-    def test_string(self):
-        mod = self.make_module("""
-            HPy_METH_NOARGS(f)
-            static HPy f_impl(HPyContext ctx, HPy self)
-            {
-                return HPyUnicode_FromString(ctx, "foobar");
-            }
-            @EXPORT f METH_NOARGS
-            @INIT
-        """)
-        assert mod.f() == "foobar"
-
     def test_bool(self):
         mod = self.make_module("""
-            HPy_METH_O(f)
+            HPy_DEF_METH_O(f)
             static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
             {
                 int cond = HPyLong_AsLong(ctx, arg) > 5;
                 return HPy_Dup(ctx, cond ? ctx->h_True : ctx->h_False);
             }
-            @EXPORT f METH_O
+            @EXPORT f HPy_METH_O
             @INIT
         """)
         assert mod.f(4) is False
@@ -162,7 +150,7 @@
     def test_exception(self):
         import pytest
         mod = self.make_module("""
-            HPy_METH_O(f)
+            HPy_DEF_METH_O(f)
             static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
             {
                 long x = HPyLong_AsLong(ctx, arg);
@@ -174,10 +162,115 @@
                     return HPy_NULL;
                 }
             }
-            @EXPORT f METH_O
+            @EXPORT f HPy_METH_O
             @INIT
         """)
         assert mod.f(-10) == 10
         with pytest.raises(ValueError) as exc:
             mod.f(20)
         assert str(exc.value) == 'hello world'
+
+    def test_builtin_handles(self):
+        import pytest
+        mod = self.make_module("""
+            HPy_DEF_METH_O(f)
+            static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
+            {
+                long i = HPyLong_AsLong(ctx, arg);
+                HPy h;
+                switch(i) {
+                    case 1: h = ctx->h_None; break;
+                    case 2: h = ctx->h_False; break;
+                    case 3: h = ctx->h_True; break;
+                    case 4: h = ctx->h_ValueError; break;
+                    case 5: h = ctx->h_TypeError; break;
+                    default:
+                        HPyErr_SetString(ctx, ctx->h_ValueError, "invalid choice");
+                        return HPy_NULL;
+                }
+                return HPy_Dup(ctx, h);
+            }
+            @EXPORT f HPy_METH_O
+            @INIT
+        """)
+        builtin_objs = ('<NULL>', None, False, True, ValueError, TypeError)
+        for i, obj in enumerate(builtin_objs):
+            if i == 0:
+                continue
+            assert mod.f(i) is obj
+
+    def test_decl_meth(self):
+        main = """
+            HPy_DECL_METH_NOARGS(f);
+            HPy_DECL_METH_O(g);
+            HPy_DECL_METH_VARARGS(h);
+
+            @EXPORT f HPy_METH_NOARGS
+            @EXPORT g HPy_METH_O
+            @EXPORT h HPy_METH_VARARGS
+            @INIT
+        """
+        extra = """
+            HPy_DEF_METH_NOARGS(f)
+            static HPy f_impl(HPyContext ctx, HPy self)
+            {
+                return HPyLong_FromLong(ctx, 12345);
+            }
+            HPy_DEF_METH_O(g)
+            static HPy g_impl(HPyContext ctx, HPy self, HPy arg)
+            {
+                return HPy_Dup(ctx, arg);
+            }
+            HPy_DEF_METH_VARARGS(h)
+            static HPy h_impl(HPyContext ctx, HPy self, HPy *args, HPy_ssize_t nargs)
+            {
+                long a, b;
+                if (!HPyArg_Parse(ctx, args, nargs, "ll", &a, &b))
+                    return HPy_NULL;
+                return HPyLong_FromLong(ctx, 10*a + b);
+            }
+        """
+        mod = self.make_module(main, extra_templates=[extra])
+        assert mod.f() == 12345
+        assert mod.g(42) == 42
+        assert mod.h(5, 6) == 56
+
+    def test_Float_FromDouble(self):
+        mod = self.make_module("""
+            HPy_DEF_METH_NOARGS(f)
+            static HPy f_impl(HPyContext ctx, HPy self)
+            {
+                return HPyFloat_FromDouble(ctx, 123.45);
+            }
+            @EXPORT f HPy_METH_NOARGS
+            @INIT
+        """)
+        assert mod.f() == 123.45
+
+    def test_Long_FromLongLong(self):
+        mod = self.make_module("""
+            HPy_DEF_METH_NOARGS(f)
+            static HPy f_impl(HPyContext ctx, HPy self)
+            {
+                // take a value which doesn't fit in 32 bit
+                long long val = 2147483648;
+                return HPyLong_FromLongLong(ctx, val);
+            }
+            @EXPORT f HPy_METH_NOARGS
+            @INIT
+        """)
+        assert mod.f() == 2147483648
+
+    def test_Long_FromUnsignedLongLong(self):
+        mod = self.make_module("""
+            HPy_DEF_METH_NOARGS(f)
+            static HPy f_impl(HPyContext ctx, HPy self)
+            {
+                // take a value which doesn't fit in unsigned 32 bit
+                unsigned long long val = 4294967296;
+                return HPyLong_FromUnsignedLongLong(ctx, val);
+            }
+            @EXPORT f HPy_METH_NOARGS
+            @INIT
+        """)
+        assert mod.f() == 4294967296
diff --git a/pypy/module/hpy_universal/_vendored/test/test_bytesobject.py b/pypy/module/hpy_universal/_vendored/test/test_bytesobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/hpy_universal/_vendored/test/test_bytesobject.py
@@ -0,0 +1,66 @@
+from .support import HPyTest
+
+class TestBytesObject(HPyTest):
+
+    def test_Check(self):
+        mod = self.make_module("""
+            HPy_DEF_METH_O(f)
+            static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
+            {
+                if (HPyBytes_Check(ctx, arg))
+                    return HPy_Dup(ctx, ctx->h_True);
+                return HPy_Dup(ctx, ctx->h_False);
+            }
+            @EXPORT f HPy_METH_O
+            @INIT
+        """)
+        assert mod.f(b'hello') is True
+        assert mod.f('hello') is False
+
+    def test_Size(self):
+        mod = self.make_module("""
+            HPy_DEF_METH_O(f)
+            static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
+            {
+                HPy_ssize_t a = HPyBytes_Size(ctx, arg);
+                HPy_ssize_t b = HPyBytes_GET_SIZE(ctx, arg);
+                return HPyLong_FromLong(ctx, 10*a + b);
+            }
+            @EXPORT f HPy_METH_O
+            @INIT
+        """)
+        assert mod.f(b'hello') == 55
+
+    def test_AsString(self):
+        mod = self.make_module("""
+            HPy_DEF_METH_O(f)
+            static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
+            {
+                long res = 0;
+                HPy_ssize_t n = HPyBytes_Size(ctx, arg);
+                char *buf = HPyBytes_AsString(ctx, arg);
+                for(int i=0; i<n; i++)
+                    res = (res * 10) + buf[i];
+                return HPyLong_FromLong(ctx, res);
+            }
+            @EXPORT f HPy_METH_O
+            @INIT
+        """)
+        assert mod.f(b'ABC') == 100*ord('A') + 10*ord('B') + ord('C')
+
+    def test_AS_STRING(self):
+        mod = self.make_module("""
+            HPy_DEF_METH_O(f)
+            static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
+            {
+                long res = 0;
+                HPy_ssize_t n = HPyBytes_Size(ctx, arg);
+                char *buf = HPyBytes_AS_STRING(ctx, arg);
+                for(int i=0; i<n; i++)
+                    res = (res * 10) + buf[i];
+                return HPyLong_FromLong(ctx, res);
+            }
+            @EXPORT f HPy_METH_O
+            @INIT
+        """)
+        assert mod.f(b'ABC') == 100*ord('A') + 10*ord('B') + ord('C')
diff --git a/pypy/module/hpy_universal/_vendored/test/test_cpy_compat.py b/pypy/module/hpy_universal/_vendored/test/test_cpy_compat.py
--- a/pypy/module/hpy_universal/_vendored/test/test_cpy_compat.py
+++ b/pypy/module/hpy_universal/_vendored/test/test_cpy_compat.py
@@ -6,7 +6,7 @@
     def test_frompyobject(self):
         mod = self.make_module("""
             #include <Python.h>
-            HPy_METH_NOARGS(f)
+            HPy_DEF_METH_NOARGS(f)
             static HPy f_impl(HPyContext ctx, HPy self)
             {
                 PyObject *o = PyList_New(0);
@@ -20,7 +20,7 @@
                 Py_DECREF(o);
                 return h;
             }
-            @EXPORT f METH_NOARGS
+            @EXPORT f HPy_METH_NOARGS
             @INIT
         """)
         x = mod.f()
@@ -29,7 +29,7 @@
     def test_hpy_close(self):
         mod = self.make_module("""
             #include <Python.h>
-            HPy_METH_NOARGS(f)
+            HPy_DEF_METH_NOARGS(f)
             static HPy f_impl(HPyContext ctx, HPy self)
             {
                 PyObject *o = PyList_New(0);
@@ -43,7 +43,7 @@
                 return HPyLong_FromLong(ctx, (long)(final_refcount -
                                                     initial_refcount));
             }
-            @EXPORT f METH_NOARGS
+            @EXPORT f HPy_METH_NOARGS
             @INIT
         """)
         assert mod.f() == -1
@@ -51,7 +51,7 @@
     def test_hpy_dup(self):
         mod = self.make_module("""
             #include <Python.h>
-            HPy_METH_NOARGS(f)
+            HPy_DEF_METH_NOARGS(f)
             static HPy f_impl(HPyContext ctx, HPy self)
             {
                 PyObject *o = PyList_New(0);
@@ -67,7 +67,7 @@
                 return HPyLong_FromLong(ctx, (long)(final_refcount -
                                                     initial_refcount));
             }
-            @EXPORT f METH_NOARGS
+            @EXPORT f HPy_METH_NOARGS
             @INIT
         """)
         assert mod.f() == +1
@@ -77,7 +77,7 @@
             #include <Python.h>
             #define NUM_HANDLES  10000
 
-            HPy_METH_NOARGS(f)
+            HPy_DEF_METH_NOARGS(f)
             static HPy f_impl(HPyContext ctx, HPy self)
             {
                 PyObject *o = PyList_New(0);
@@ -99,7 +99,67 @@
              error:
                 return HPyLong_FromLong(ctx, (long)result);
             }
+            @EXPORT f HPy_METH_NOARGS
+            @INIT
+        """)
+        assert mod.f() == 0
+
+    def test_meth_cpy_noargs(self):
+        mod = self.make_module("""
+            #include <Python.h>
+
+            static PyObject *f(PyObject *self, PyObject *args)
+            {
+                return PyLong_FromLong(1234);
+            }
             @EXPORT f METH_NOARGS
             @INIT
         """)
-        assert mod.f() == 0
+        assert mod.f() == 1234
+
+    def test_meth_cpy_o(self):
+        mod = self.make_module("""
+            #include <Python.h>
+
+            static PyObject *f(PyObject *self, PyObject *arg)
+            {
+                long x = PyLong_AsLong(arg);
+                return PyLong_FromLong(x * 2);
+            }
+            @EXPORT f METH_O
+            @INIT
+        """)
+        assert mod.f(45) == 90
+
+    def test_meth_cpy_varargs(self):
+        mod = self.make_module("""
+            #include <Python.h>
+
+            static PyObject *f(PyObject *self, PyObject *args)
+            {
+                long a, b, c;
+                if (!PyArg_ParseTuple(args, "lll", &a, &b, &c))
+                    return NULL;
+                return PyLong_FromLong(100*a + 10*b + c);
+            }
+            @EXPORT f METH_VARARGS
+            @INIT
+        """)
+        assert mod.f(4, 5, 6) == 456
+
+    def test_meth_cpy_keywords(self):
+        mod = self.make_module("""
+            #include <Python.h>
+
+            static PyObject *f(PyObject *self, PyObject *args, PyObject *kwargs)
+            {
+                static char *kwlist[] = { "a", "b", "c", NULL };
+                long a, b, c;
+                if (!PyArg_ParseTupleAndKeywords(args, kwargs, "lll", kwlist, &a, &b, &c))
+                    return NULL;
+                return PyLong_FromLong(100*a + 10*b + c);
+            }
+            @EXPORT f METH_VARARGS | METH_KEYWORDS
+            @INIT
+        """)
+        assert mod.f(c=6, b=5, a=4) == 456
diff --git a/pypy/module/hpy_universal/_vendored/test/test_dictobject.py b/pypy/module/hpy_universal/_vendored/test/test_dictobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/hpy_universal/_vendored/test/test_dictobject.py
@@ -0,0 +1,33 @@
+from .support import HPyTest
+
+class TestDictObject(HPyTest):
+
+    def test_New(self):
+        mod = self.make_module("""
+            HPy_DEF_METH_NOARGS(f)
+            static HPy f_impl(HPyContext ctx, HPy self)
+            {
+                return HPyDict_New(ctx);
+            }
+            @EXPORT f HPy_METH_NOARGS
+            @INIT
+        """)
+        assert mod.f() == {}
+
+    def test_SetItem(self):
+        mod = self.make_module("""
+            HPy_DEF_METH_O(f)
+            static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
+            {
+                HPy dict = HPyDict_New(ctx);
+                if (HPy_IsNull(dict))
+                    return HPy_NULL;
+                HPy val = HPyLong_FromLong(ctx, 1234);
+                if (HPyDict_SetItem(ctx, dict, arg, val) == -1)
+                    return HPy_NULL;
+                return dict;
+            }
+            @EXPORT f HPy_METH_O
+            @INIT
+        """)
+        assert mod.f('hello') == {'hello': 1234}
diff --git a/pypy/module/hpy_universal/_vendored/test/test_listobject.py b/pypy/module/hpy_universal/_vendored/test/test_listobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/hpy_universal/_vendored/test/test_listobject.py
@@ -0,0 +1,34 @@
+from .support import HPyTest
+
+class TestListObject(HPyTest):
+
+    def test_New(self):
+        mod = self.make_module("""
+            HPy_DEF_METH_NOARGS(f)
+            static HPy f_impl(HPyContext ctx, HPy self)
+            {
+                return HPyList_New(ctx, 0);
+            }
+            @EXPORT f HPy_METH_NOARGS
+            @INIT
+        """)
+        assert mod.f() == []
+
+    def test_Append(self):
+        mod = self.make_module("""
+            HPy_DEF_METH_O(f)
+            static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
+            {
+                HPy list = HPyList_New(ctx, 0);
+                if (HPy_IsNull(list))
+                    return HPy_NULL;
+                if (HPyList_Append(ctx, list, arg) == -1)
+                    return HPy_NULL;
+                if (HPyList_Append(ctx, list, arg) == -1)
+                    return HPy_NULL;
+                return list;
+            }
+            @EXPORT f HPy_METH_O
+            @INIT
+        """)
+        assert mod.f(42) == [42, 42]
diff --git a/pypy/module/hpy_universal/_vendored/test/test_support.py b/pypy/module/hpy_universal/_vendored/test/test_support.py
--- a/pypy/module/hpy_universal/_vendored/test/test_support.py
+++ b/pypy/module/hpy_universal/_vendored/test/test_support.py
@@ -1,13 +1,19 @@
 from . import support
 
-
 def test_expand_template():
     expanded = support.expand_template("""
-        @EXPORT test_f METH_O
+        @EXPORT test_f HPy_METH_NOARGS
+        @EXPORT test_g METH_O
+        @EXPORT test_h METH_VARARGS | METH_KEYWORDS
         some more C stuff
         @INIT
     """, name='mytest')
-    methods = '{"test_f", test_f, METH_O, NULL},'
+    method_table = [
+        '{"test_f", test_f, HPy_METH_NOARGS, NULL},',
+        '{"test_g", (HPyMeth)test_g, METH_O, NULL},',
+        '{"test_h", (HPyMeth)test_h, METH_VARARGS | METH_KEYWORDS, NULL},'
+        ]
+    methods = '\n    '.join(method_table)
     init_code = support.INIT_TEMPLATE % {'methods': methods, 'name': 'mytest'}
     assert expanded.rstrip() == f"""#include <hpy.h>
 
diff --git a/pypy/module/hpy_universal/_vendored/test/test_unicodeobject.py b/pypy/module/hpy_universal/_vendored/test/test_unicodeobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/hpy_universal/_vendored/test/test_unicodeobject.py
@@ -0,0 +1,64 @@
+# -*- encoding: utf-8 -*-
+
+from .support import HPyTest
+
+class TestUnicodeObject(HPyTest):
+
+    def test_Check(self):
+        mod = self.make_module("""
+            HPy_DEF_METH_O(f)
+            static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
+            {
+                if (HPyUnicode_Check(ctx, arg))
+                    return HPy_Dup(ctx, ctx->h_True);
+                return HPy_Dup(ctx, ctx->h_False);
+            }
+            @EXPORT f HPy_METH_O
+            @INIT
+        """)
+        assert mod.f('hello') is True
+        assert mod.f(b'hello') is False
+
+    def test_FromString(self):
+        mod = self.make_module("""
+            HPy_DEF_METH_NOARGS(f)
+            static HPy f_impl(HPyContext ctx, HPy self)
+            {
+                return HPyUnicode_FromString(ctx, "foobar");
+            }
+            @EXPORT f HPy_METH_NOARGS
+            @INIT
+        """)
+        assert mod.f() == "foobar"
+
+    def test_FromWideChar(self):
+        mod = self.make_module("""
+            HPy_DEF_METH_O(f)
+            static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
+            {
+                const wchar_t *buf = L"hell\xf2 world";
+                long n = HPyLong_AsLong(ctx, arg);
+                return HPyUnicode_FromWideChar(ctx, buf, n);
+            }
+            @EXPORT f HPy_METH_O
+            @INIT
+        """)
+        assert mod.f(-1) == "hellò world"
+        assert mod.f(11) == "hellò world"
+        assert mod.f(5) == "hellò"
+
+
+    def test_AsUTF8String(self):
+        mod = self.make_module("""
+            HPy_DEF_METH_O(f)
+            static HPy f_impl(HPyContext ctx, HPy self, HPy arg)
+            {
+                return HPyUnicode_AsUTF8String(ctx, arg);
+            }
+            @EXPORT f HPy_METH_O
+            @INIT
+        """)
+        s = 'hellò'
+        b = mod.f(s)
+        assert type(b) is bytes
+        assert b == s.encode('utf-8')


More information about the pypy-commit mailing list