[pypy-commit] cffi cffi-1.0: ffi.new_handle(), ffi.from_handle()

arigo noreply at buildbot.pypy.org
Sat Apr 25 15:05:51 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: cffi-1.0
Changeset: r1826:e76db3405d4b
Date: 2015-04-25 15:04 +0200
http://bitbucket.org/cffi/cffi/changeset/e76db3405d4b/

Log:	ffi.new_handle(), ffi.from_handle()

diff --git a/_cffi1/ffi_obj.c b/_cffi1/ffi_obj.c
--- a/_cffi1/ffi_obj.c
+++ b/_cffi1/ffi_obj.c
@@ -464,17 +464,21 @@
     return res;
 }
 
-#if 0
-static PyObject *ffi_new_handle(ZefFFIObject *self, PyObject *arg)
+PyDoc_STRVAR(ffi_new_handle_doc,
+"Return a non-NULL cdata of type 'void *' that contains an opaque\n"
+"reference to the argument, which can be any Python object.  To cast it\n"
+"back to the original object, use from_handle().  You must keep alive\n"
+"the cdata object returned by new_handle()!");
+
+static PyObject *ffi_new_handle(FFIObject *self, PyObject *arg)
 {
-    CTypeDescrObject *ct = ZefNULL->c_type;   // <ctype 'void *'>
     CDataObject *cd;
 
     cd = (CDataObject *)PyObject_GC_New(CDataObject, &CDataOwningGC_Type);
     if (cd == NULL)
         return NULL;
-    Py_INCREF(ct);
-    cd->c_type = ct;
+    Py_INCREF(g_ct_voidp);     // <ctype 'void *'>
+    cd->c_type = g_ct_voidp;
     Py_INCREF(arg);
     cd->c_data = ((char *)arg) - 42;
     cd->c_weakreflist = NULL;
@@ -482,6 +486,12 @@
     return (PyObject *)cd;
 }
 
+PyDoc_STRVAR(ffi_from_handle_doc,
+"Cast a 'void *' back to a Python object.  Must be used *only* on the\n"
+"pointers returned by new_handle(), and *only* as long as the exact\n"
+"cdata object returned by new_handle() is still alive (somewhere else\n"
+"in the program).  Failure to follow these rules will crash.");
+
 static PyObject *ffi_from_handle(PyObject *self, PyObject *arg)
 {
     CTypeDescrObject *ct;
@@ -509,6 +519,7 @@
     return x;
 }
 
+#if 0
 static PyObject *ffi_gc(ZefFFIObject *self, PyObject *args)
 {
     CDataObject *cd;
@@ -681,16 +692,14 @@
  {"callback",   (PyCFunction)ffi_callback,   METH_VARARGS |
                                              METH_KEYWORDS,ffi_callback_doc},
  {"cast",       (PyCFunction)ffi_cast,       METH_VARARGS, ffi_cast_doc},
+ {"from_handle",(PyCFunction)ffi_from_handle,METH_O,       ffi_from_handle_doc},
 #if 0
- {"from_handle",(PyCFunction)ffi_from_handle,METH_O},
  {"gc",         (PyCFunction)ffi_gc,         METH_VARARGS},
 #endif
  {"getctype",   (PyCFunction)ffi_getctype,   METH_VARARGS, ffi_getctype_doc},
  {"offsetof",   (PyCFunction)ffi_offsetof,   METH_VARARGS, ffi_offsetof_doc},
  {"new",        (PyCFunction)ffi_new,        METH_VARARGS, ffi_new_doc},
-#if 0
- {"new_handle", (PyCFunction)ffi_new_handle, METH_O},
-#endif
+ {"new_handle", (PyCFunction)ffi_new_handle, METH_O,       ffi_new_handle_doc},
  {"sizeof",     (PyCFunction)ffi_sizeof,     METH_O,       ffi_sizeof_doc},
  {"string",     (PyCFunction)ffi_string,     METH_VARARGS, ffi_string_doc},
  {"typeof",     (PyCFunction)ffi_typeof,     METH_O,       ffi_typeof_doc},
diff --git a/_cffi1/realize_c_type.c b/_cffi1/realize_c_type.c
--- a/_cffi1/realize_c_type.c
+++ b/_cffi1/realize_c_type.c
@@ -8,6 +8,7 @@
 
 static PyObject *all_primitives[_CFFI__NUM_PRIM];
 static PyObject *global_types_dict;
+static CTypeDescrObject *g_ct_voidp;
 
 static PyObject *build_primitive_type(int num);   /* forward */
 
@@ -39,9 +40,9 @@
         Py_DECREF(ct2);
         return -1;
     }
+    g_ct_voidp = (CTypeDescrObject *)ct2;
 
     pnull = new_simple_cdata(NULL, (CTypeDescrObject *)ct2);
-    Py_DECREF(ct2);
     if (pnull == NULL)
         return -1;
     err = PyDict_SetItemString(ffi_type_dict, "NULL", pnull);
diff --git a/_cffi1/test_ffi_obj.py b/_cffi1/test_ffi_obj.py
--- a/_cffi1/test_ffi_obj.py
+++ b/_cffi1/test_ffi_obj.py
@@ -121,3 +121,12 @@
     b = ffi.addressof(a, 5)
     b[2] = -123
     assert a[7] == -123
+
+def test_handle():
+    ffi = _cffi1_backend.FFI()
+    x = [2, 4, 6]
+    xp = ffi.new_handle(x)
+    assert ffi.typeof(xp) == ffi.typeof("void *")
+    assert ffi.from_handle(xp) is x
+    yp = ffi.new_handle([6, 4, 2])
+    assert ffi.from_handle(yp) == [6, 4, 2]


More information about the pypy-commit mailing list