[pypy-commit] pypy rffi-parser-2: Add a way to create API functions using C declarations; try to use it
rlamy
pypy.commits at gmail.com
Thu Jan 12 11:41:54 EST 2017
Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: rffi-parser-2
Changeset: r89520:05b94a8b7e3d
Date: 2017-01-12 16:40 +0000
http://bitbucket.org/pypy/pypy/changeset/05b94a8b7e3d/
Log: Add a way to create API functions using C declarations; try to use
it
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -246,13 +246,15 @@
class ApiFunction(object):
def __init__(self, argtypes, restype, callable, error=CANNOT_FAIL,
- c_name=None, gil=None, result_borrowed=False, result_is_ll=False):
+ c_name=None, cdecl=None, gil=None,
+ result_borrowed=False, result_is_ll=False):
self.argtypes = argtypes
self.restype = restype
self.functype = lltype.Ptr(lltype.FuncType(argtypes, restype))
self.callable = callable
self.error_value = error
self.c_name = c_name
+ self.cdecl = cdecl
# extract the signature from the (CPython-level) code object
from pypy.interpreter import pycode
@@ -371,6 +373,8 @@
return unwrapper
def get_c_restype(self, c_writer):
+ if self.cdecl:
+ return self.cdecl.split(self.c_name)[0].strip()
return c_writer.gettype(self.restype).replace('@', '').strip()
def get_c_args(self, c_writer):
@@ -470,6 +474,20 @@
return unwrapper
return decorate
+def api_decl(cdecl, cts, error=_NOT_SPECIFIED, header=DEFAULT_HEADER):
+ def decorate(func):
+ func._always_inline_ = 'try'
+ name, FUNC = cts.parse_func(cdecl)
+ api_function = ApiFunction(
+ FUNC.ARGS, FUNC.RESULT, func,
+ error=_compute_error(error, FUNC.RESULT), cdecl=cdecl)
+ FUNCTIONS_BY_HEADER[header][name] = api_function
+ unwrapper = api_function.get_unwrapper()
+ unwrapper.func = func
+ unwrapper.api_func = api_function
+ return unwrapper
+ return decorate
+
def slot_function(argtypes, restype, error=_NOT_SPECIFIED):
def decorate(func):
func._always_inline_ = 'try'
diff --git a/pypy/module/cpyext/methodobject.py b/pypy/module/cpyext/methodobject.py
--- a/pypy/module/cpyext/methodobject.py
+++ b/pypy/module/cpyext/methodobject.py
@@ -11,12 +11,10 @@
CONST_STRING, METH_CLASS, METH_COEXIST, METH_KEYWORDS, METH_NOARGS, METH_O,
METH_STATIC, METH_VARARGS, PyObject, PyObjectFields, bootstrap_function,
build_type_checkers, cpython_api, cpython_struct, generic_cpy_call,
- PyTypeObjectPtr, slot_function, object_h)
+ PyTypeObjectPtr, slot_function, object_h, api_decl)
from pypy.module.cpyext.pyobject import (
Py_DecRef, from_ref, make_ref, as_pyobj, make_typedescr)
-PyCFunction_typedef = rffi.COpaquePtr(typedef='PyCFunction')
-
PyMethodDef = object_h.gettype('PyMethodDef')
PyCFunction = object_h.gettype('PyCFunction')
PyCFunctionKwArgs = object_h.gettype('PyCFunctionWithKeywords')
@@ -284,7 +282,7 @@
def PyCFunction_NewEx(space, ml, w_self, w_name):
return space.wrap(W_PyCFunctionObject(space, ml, w_self, w_name))
- at cpython_api([PyObject], PyCFunction_typedef)
+ at api_decl("PyCFunction PyCFunction_GetFunction(PyObject *)", object_h)
def PyCFunction_GetFunction(space, w_obj):
try:
cfunction = space.interp_w(W_PyCFunctionObject, w_obj)
diff --git a/pypy/module/cpyext/test/test_methodobject.py b/pypy/module/cpyext/test/test_methodobject.py
--- a/pypy/module/cpyext/test/test_methodobject.py
+++ b/pypy/module/cpyext/test/test_methodobject.py
@@ -4,7 +4,7 @@
from pypy.module.cpyext.api import ApiFunction
from pypy.module.cpyext.pyobject import PyObject, make_ref, Py_DecRef
from pypy.module.cpyext.methodobject import (
- PyDescr_NewMethod, PyCFunction_typedef)
+ PyDescr_NewMethod, PyCFunction)
from rpython.rtyper.lltypesystem import rffi, lltype
class AppTestMethodObject(AppTestCpythonExtensionBase):
@@ -67,7 +67,7 @@
'''
PyCFunction ptr = PyCFunction_GetFunction(args);
if (!ptr) return NULL;
- if (ptr == MyModule_getarg_O)
+ if (ptr == (PyCFunction)MyModule_getarg_O)
Py_RETURN_TRUE;
else
Py_RETURN_FALSE;
@@ -105,8 +105,7 @@
ml = lltype.malloc(PyMethodDef, flavor='raw', zero=True)
namebuf = rffi.cast(rffi.CONST_CCHARP, rffi.str2charp('func'))
ml.c_ml_name = namebuf
- ml.c_ml_meth = rffi.cast(PyCFunction_typedef,
- c_func.get_llhelper(space))
+ ml.c_ml_meth = rffi.cast(PyCFunction, c_func.get_llhelper(space))
method = api.PyDescr_NewMethod(space.w_str, ml)
assert repr(method).startswith(
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -19,7 +19,7 @@
Py_TPFLAGS_HAVE_NEWBUFFER, Py_TPFLAGS_CHECKTYPES,
Py_TPFLAGS_HAVE_INPLACEOPS)
from pypy.module.cpyext.methodobject import (W_PyCClassMethodObject,
- W_PyCWrapperObject, PyCFunction_NewEx, PyCFunction_typedef, PyMethodDef,
+ W_PyCWrapperObject, PyCFunction_NewEx, PyCFunction, PyMethodDef,
W_PyCMethodObject, W_PyCFunctionObject)
from pypy.module.cpyext.modsupport import convert_method_defs
from pypy.module.cpyext.pyobject import (
@@ -386,8 +386,7 @@
def setup_new_method_def(space):
ptr = get_new_method_def(space)
- ptr.c_ml_meth = rffi.cast(
- PyCFunction_typedef, llslot(space, tp_new_wrapper))
+ ptr.c_ml_meth = rffi.cast(PyCFunction, llslot(space, tp_new_wrapper))
def add_tp_new_wrapper(space, dict_w, pto):
if "__new__" in dict_w:
More information about the pypy-commit
mailing list