Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r184:f6141dc25e53
Date: 2014-12-05 21:56 +0100
http://bitbucket.org/cffi/creflect/changeset/f6141dc25e53/

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

diff --git a/zeffir/cdata.c b/zeffir/cdata.c
--- a/zeffir/cdata.c
+++ b/zeffir/cdata.c
@@ -1,10 +1,10 @@
 
-typedef struct {
+struct cdataobject_s {
     PyObject_HEAD
     CTypeDescrObject *c_type;
     char *c_data;
     PyObject *c_weakreflist;
-} CDataObject;
+};
 
 typedef union {
     unsigned char m_char;
@@ -884,64 +884,59 @@
 //1491
 static void cdataowninggc_dealloc(CDataObject *cd)
 {
-    abort();
-#if 0
-    assert(!(cd->c_type->ct_flags & (CT_IS_PTR_TO_OWNED |
-                                     CT_PRIMITIVE_ANY |
-                                     CT_STRUCT | CT_UNION)));
+    assert(!(cd->c_type->ct_flags & (CT_PRIMITIVE_ANY | CT_STRUCT | 
CT_UNION)));
     PyObject_GC_UnTrack(cd);
 
     if (cd->c_type->ct_flags & CT_IS_VOID_PTR) {        /* a handle */
         PyObject *x = (PyObject *)(cd->c_data + 42);
         Py_DECREF(x);
     }
+#if 0
     else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) {   /* a callback */
         ffi_closure *closure = (ffi_closure *)cd->c_data;
         PyObject *args = (PyObject *)(closure->user_data);
         Py_XDECREF(args);
         cffi_closure_free(closure);
     }
+#endif
     cdata_dealloc(cd);
-#endif
 }
 
 //1534
 static int cdataowninggc_traverse(CDataObject *cd, visitproc visit, void *arg)
 {
-    abort();
-#if 0
     if (cd->c_type->ct_flags & CT_IS_VOID_PTR) {        /* a handle */
         PyObject *x = (PyObject *)(cd->c_data + 42);
         Py_VISIT(x);
     }
+#if 0
     else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) {   /* a callback */
         ffi_closure *closure = (ffi_closure *)cd->c_data;
         PyObject *args = (PyObject *)(closure->user_data);
         Py_VISIT(args);
     }
+#endif
     return 0;
-#endif
 }
 
 //1548
 static int cdataowninggc_clear(CDataObject *cd)
 {
-    abort();
-#if 0
     if (cd->c_type->ct_flags & CT_IS_VOID_PTR) {        /* a handle */
         PyObject *x = (PyObject *)(cd->c_data + 42);
         Py_INCREF(Py_None);
         cd->c_data = ((char *)Py_None) - 42;
         Py_DECREF(x);
     }
+#if 0
     else if (cd->c_type->ct_flags & CT_FUNCTIONPTR) {   /* a callback */
         ffi_closure *closure = (ffi_closure *)cd->c_data;
         PyObject *args = (PyObject *)(closure->user_data);
         closure->user_data = NULL;
         Py_XDECREF(args);
     }
+#endif
     return 0;
-#endif
 }
 
 //1599
@@ -1644,7 +1639,7 @@
     (reprfunc)cdataowning_repr,                 /* tp_repr */
     0,                                          /* tp_as_number */
     0,                                          /* tp_as_sequence */
-    0,//&CDataOwn_as_mapping,                       /* tp_as_mapping */
+    0,                                          /* tp_as_mapping */
     0,                                          /* tp_hash */
     0,                                          /* tp_call */
     0,                                          /* tp_str */
diff --git a/zeffir/ffi_obj.c b/zeffir/ffi_obj.c
--- a/zeffir/ffi_obj.c
+++ b/zeffir/ffi_obj.c
@@ -684,19 +684,64 @@
     return res;
 }
 
+static PyObject *ffi_new_handle(ZefFFIObject *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(arg);
+    cd->c_data = ((char *)arg) - 42;
+    cd->c_weakreflist = NULL;
+    PyObject_GC_Track(cd);
+    return (PyObject *)cd;
+}
+
+static PyObject *ffi_from_handle(PyObject *self, PyObject *arg)
+{
+    CTypeDescrObject *ct;
+    char *raw;
+    PyObject *x;
+    if (!CData_Check(arg)) {
+        PyErr_SetString(PyExc_TypeError, "expected a 'cdata' object");
+        return NULL;
+    }
+    ct = ((CDataObject *)arg)->c_type;
+    raw = ((CDataObject *)arg)->c_data;
+    if (!(ct->ct_flags & CT_CAST_ANYTHING)) {
+        PyErr_Format(PyExc_TypeError,
+                     "expected a 'cdata' object with a 'void *' out of "
+                     "new_handle(), got '%s'", ct->ct_name);
+        return NULL;
+    }
+    if (!raw) {
+        PyErr_SetString(PyExc_RuntimeError,
+                        "cannot use from_handle() on NULL pointer");
+        return NULL;
+    }
+    x = (PyObject *)(raw + 42);
+    Py_INCREF(x);
+    return x;
+}
+
 
 static PyMethodDef ffi_methods[] = {
-    {"addressof",     (PyCFunction)ffi_addressof,METH_VARARGS},
-    {"cast",          (PyCFunction)ffi_cast,     METH_VARARGS},
-    {"close_library", ffi_close_library,         METH_VARARGS | METH_STATIC},
-    {"getctype",      (PyCFunction)ffi_getctype, METH_VARARGS},
-    {"load_library",  (PyCFunction)ffi_load_library,
-                                                 METH_VARARGS | METH_KEYWORDS},
-    {"offsetof",      (PyCFunction)ffi_offsetof, METH_VARARGS},
-    {"new",           (PyCFunction)ffi_new,      METH_VARARGS},
-    {"sizeof",        (PyCFunction)ffi_sizeof,   METH_O},
-    {"string",        (PyCFunction)ffi_string,   METH_VARARGS},
-    {"typeof",        (PyCFunction)ffi_typeof,   METH_O},
+    {"addressof",     (PyCFunction)ffi_addressof, METH_VARARGS},
+    {"cast",          (PyCFunction)ffi_cast,      METH_VARARGS},
+    {"close_library", ffi_close_library,          METH_VARARGS | METH_STATIC},
+    {"from_handle",   (PyCFunction)ffi_from_handle,METH_O},
+    {"getctype",      (PyCFunction)ffi_getctype,  METH_VARARGS},
+    {"load_library",  
(PyCFunction)ffi_load_library,METH_VARARGS|METH_KEYWORDS},
+    {"offsetof",      (PyCFunction)ffi_offsetof,  METH_VARARGS},
+    {"new",           (PyCFunction)ffi_new,       METH_VARARGS},
+    {"new_handle",    (PyCFunction)ffi_new_handle,METH_O},
+    {"sizeof",        (PyCFunction)ffi_sizeof,    METH_O},
+    {"string",        (PyCFunction)ffi_string,    METH_VARARGS},
+    {"typeof",        (PyCFunction)ffi_typeof,    METH_O},
     {NULL}
 };
 
diff --git a/zeffir/test/test_basic.py b/zeffir/test/test_basic.py
--- a/zeffir/test/test_basic.py
+++ b/zeffir/test/test_basic.py
@@ -72,3 +72,12 @@
     assert ffi.getctype("int[5]", '*') == "int(*)[5]"
     assert ffi.getctype("int[5]", '*foo') == "int(*foo)[5]"
     assert ffi.getctype("int[5]", ' ** foo ') == "int(** foo)[5]"
+
+def test_from_handle():
+    ffi = support.new_ffi()
+    x = [5, 6]
+    x.append(7)
+    p = ffi.new_handle(x)
+    assert ffi.from_handle(p) is x
+    del x
+    assert ffi.from_handle(p) == [5, 6, 7]
diff --git a/zeffir/zeffir.c b/zeffir/zeffir.c
--- a/zeffir/zeffir.c
+++ b/zeffir/zeffir.c
@@ -73,16 +73,17 @@
 
     {
         CTypeDescrObject *ctvoidp;
-        PyObject *cdnull;
         PyObject *d1 = PyDict_New();
         if (d1 == NULL)
             return;
 
         ctvoidp = parse_c_decl(d1, "void*");
         if (ctvoidp) {
-            cdnull = new_simple_cdata(NULL, ctvoidp);
-            if (cdnull)
-                PyDict_SetItemString(ZefFFI_Type.tp_dict, "NULL", cdnull);
+            ZefNULL = (CDataObject *)new_simple_cdata(NULL, ctvoidp);
+            if (ZefNULL) {
+                PyDict_SetItemString(ZefFFI_Type.tp_dict, "NULL",
+                                     (PyObject *)ZefNULL);
+            }
         }
         Py_DECREF(d1);
         if (PyErr_Occurred())
diff --git a/zeffir/zeffir.h b/zeffir/zeffir.h
--- a/zeffir/zeffir.h
+++ b/zeffir/zeffir.h
@@ -1,5 +1,6 @@
 
 typedef struct _crx_type_s CTypeDescrObject;
+typedef struct cdataobject_s CDataObject;
 typedef struct cfieldobject_s CFieldObject;
 typedef struct ZefLibObject_s ZefLibObject;
 typedef struct ZefFFIObject_s ZefFFIObject;
@@ -12,6 +13,7 @@
 static PyTypeObject CDataOwningGC_Type;
 
 static PyObject *ZefError;
+static CDataObject *ZefNULL;
 
 static int lib_close(ZefLibObject *);
 static int load_creflect_main(ZefFFIObject *, ZefLibObject *);
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to