Author: Antonio Cuni <[email protected]>
Branch: hpy
Changeset: r98519:bbc0f966d0be
Date: 2020-01-10 21:27 +0100
http://bitbucket.org/pypy/pypy/changeset/bbc0f966d0be/
Log: add support for legacy methods using the old C-API calling
convention, which are wrapped through the cpyext machinery;
test_cpy_compat now fully passes :)
diff --git a/pypy/module/hpy_universal/interp_module.py
b/pypy/module/hpy_universal/interp_module.py
--- a/pypy/module/hpy_universal/interp_module.py
+++ b/pypy/module/hpy_universal/interp_module.py
@@ -17,13 +17,42 @@
if hpydef.c_m_methods:
p = hpydef.c_m_methods
i = 0
+ legacy_methoddefs = [] # for those using the old C-API calling
convention
while p[i].c_ml_name:
- if not widen(p[i].c_ml_flags) & llapi._HPy_METH:
- # we need to add support for legacy methods through cpyext
- raise oefmt(space.w_NotImplementedError, "non-hpy method: %s",
- rffi.constcharp2str(p[i].c_ml_name))
- w_extfunc = interp_extfunc.W_ExtensionFunction(p[i], w_mod)
- space.setattr(w_mod, space.newtext(w_extfunc.name), w_extfunc)
+ if widen(p[i].c_ml_flags) & llapi._HPy_METH:
+ # hpy native methods
+ w_extfunc = interp_extfunc.W_ExtensionFunction(p[i], w_mod)
+ space.setattr(w_mod, space.newtext(w_extfunc.name), w_extfunc)
+ else:
+ # legacy cpyext-based methods, to be processed later
+ legacy_methoddefs.append(p[i])
i += 1
+ if legacy_methoddefs:
+ attach_legacy_methods(space, legacy_methoddefs, w_mod, modname)
#
return handles.new(space, w_mod)
+
+
+def attach_legacy_methods(space, hpymethods, w_mod, modname):
+ from pypy.module.cpyext.methodobject import PyMethodDef, PyCFunction
+ from pypy.module.cpyext.modsupport import convert_method_defs
+ PyMethodDefP = rffi.CArrayPtr(PyMethodDef)
+
+ # convert hpymethods into a C array of PyMethodDef
+ dict_w = {}
+ n = len(hpymethods)
+ with lltype.scoped_alloc(PyMethodDefP.TO, n+1) as pymethods:
+ for i in range(n):
+ src = hpymethods[i] # HPyMethodDef
+ dst = pymethods[i] # PyMethodDef
+ dst.c_ml_name = src.c_ml_name
+ dst.c_ml_doc = src.c_ml_doc
+ # for legacy methods, ml_meth contains a PyCFunction which can be
+ # called using the old C-API/cpyext calling convention
+ dst.c_ml_meth = rffi.cast(PyCFunction, src.c_ml_meth)
+ rffi.setintfield(dst, 'c_ml_flags', widen(src.c_ml_flags) &
~llapi._HPy_METH)
+ pymethods[n].c_ml_name = lltype.nullptr(rffi.CONST_CCHARP.TO)
+ convert_method_defs(space, dict_w, pymethods, None, w_mod, modname)
+
+ for key, w_func in dict_w.items():
+ space.setattr(w_mod, space.newtext(key), w_func)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit