[pypy-commit] cffi cffi-1.0: ffi.gc(), copied straight from zeffir

arigo noreply at buildbot.pypy.org
Sun Apr 26 11:29:08 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r1841:e0ca28cfacbd
Date: 2015-04-26 11:29 +0200
http://bitbucket.org/cffi/cffi/changeset/e0ca28cfacbd/

Log:	ffi.gc(), copied straight from zeffir

diff --git a/_cffi1/cffi1_module.c b/_cffi1/cffi1_module.c
--- a/_cffi1/cffi1_module.c
+++ b/_cffi1/cffi1_module.c
@@ -10,6 +10,7 @@
 
 #include "ffi_obj.c"
 #include "cglob.c"
+#include "cgc.c"
 #include "lib_obj.c"
 
 
diff --git a/_cffi1/cgc.c b/_cffi1/cgc.c
new file mode 100644
--- /dev/null
+++ b/_cffi1/cgc.c
@@ -0,0 +1,80 @@
+
+/* translated to C from cffi/gc_weakref.py */
+
+
+static PyObject *const_name_pop;
+
+static PyObject *gc_wref_remove(PyObject *ffi_wref_data, PyObject *arg)
+{
+    PyObject *destructor, *cdata, *x;
+    PyObject *res = PyObject_CallMethodObjArgs(ffi_wref_data,
+                                               const_name_pop, arg, NULL);
+    if (res == NULL)
+        return NULL;
+
+    assert(PyTuple_Check(res));
+    destructor = PyTuple_GET_ITEM(res, 0);
+    cdata = PyTuple_GET_ITEM(res, 1);
+    x = PyObject_CallFunctionObjArgs(destructor, cdata, NULL);
+    Py_DECREF(res);
+    if (x == NULL)
+        return NULL;
+    Py_DECREF(x);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyMethodDef remove_callback = {
+    "gc_wref_remove", (PyCFunction)gc_wref_remove, METH_O
+};
+
+static PyObject *gc_weakrefs_build(FFIObject *ffi, CDataObject *cd,
+                                   PyObject *destructor)
+{
+    PyObject *new_cdata, *ref = NULL, *tup = NULL;
+
+    if (ffi->gc_wrefs == NULL) {
+        /* initialize */
+        PyObject *data;
+
+        if (const_name_pop == NULL) {
+            const_name_pop = PyString_InternFromString("pop");
+            if (const_name_pop == NULL)
+                return NULL;
+        }
+        data = PyDict_New();
+        if (data == NULL)
+            return NULL;
+        ffi->gc_wrefs = PyCFunction_New(&remove_callback, data);
+        Py_DECREF(data);
+        if (ffi->gc_wrefs == NULL)
+            return NULL;
+    }
+
+    new_cdata = do_cast(cd->c_type, (PyObject *)cd);
+    if (new_cdata == NULL)
+        goto error;
+
+    ref = PyWeakref_NewRef(new_cdata, ffi->gc_wrefs);
+    if (ref == NULL)
+        goto error;
+
+    tup = PyTuple_Pack(2, destructor, cd);
+    if (tup == NULL)
+        goto error;
+
+    /* the 'self' of the function 'gc_wrefs' is actually the data dict */
+    if (PyDict_SetItem(PyCFunction_GET_SELF(ffi->gc_wrefs), ref, tup) < 0)
+        goto error;
+
+    Py_DECREF(tup);
+    Py_DECREF(ref);
+    return new_cdata;
+
+ error:
+    Py_XDECREF(new_cdata);
+    Py_XDECREF(ref);
+    Py_XDECREF(tup);
+    return NULL;
+}
diff --git a/_cffi1/ffi_obj.c b/_cffi1/ffi_obj.c
--- a/_cffi1/ffi_obj.c
+++ b/_cffi1/ffi_obj.c
@@ -546,8 +546,15 @@
     return direct_from_buffer(g_ct_chararray, arg);
 }
 
-#if 0
-static PyObject *ffi_gc(ZefFFIObject *self, PyObject *args)
+PyDoc_STRVAR(ffi_gc_doc,
+"Return a new cdata object that points to the same data.\n"
+"Later, when this new cdata object is garbage-collected,\n"
+"'destructor(old_cdata_object)' will be called.");
+
+static PyObject *gc_weakrefs_build(FFIObject *ffi, CDataObject *cd,
+                                   PyObject *destructor);   /* forward */
+
+static PyObject *ffi_gc(FFIObject *self, PyObject *args)
 {
     CDataObject *cd;
     PyObject *destructor;
@@ -557,7 +564,6 @@
 
     return gc_weakrefs_build(self, cd, destructor);
 }
-#endif
 
 PyDoc_STRVAR(ffi_callback_doc,
 "Return a callback object or a decorator making such a callback object.\n"
@@ -731,9 +737,7 @@
  {"cast",       (PyCFunction)ffi_cast,       METH_VARARGS, ffi_cast_doc},
  {"from_buffer",(PyCFunction)ffi_from_buffer,METH_O,       ffi_from_buffer_doc},
  {"from_handle",(PyCFunction)ffi_from_handle,METH_O,       ffi_from_handle_doc},
-#if 0
- {"gc",         (PyCFunction)ffi_gc,         METH_VARARGS},
-#endif
+ {"gc",         (PyCFunction)ffi_gc,         METH_VARARGS, ffi_gc_doc},
  {"getctype",   (PyCFunction)ffi_getctype,   METH_VARARGS, ffi_getctype_doc},
 #ifdef MS_WIN32
  {"getwinerror",(PyCFunction)ffi_getwinerror,METH_VARARGS, ffi_getwinerror_doc},


More information about the pypy-commit mailing list