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

Reply via email to