[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