[pypy-commit] cffi default: Add ffi.CData and ffi.CType.

arigo noreply at buildbot.pypy.org
Tue Sep 4 15:26:34 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r917:41a7f979ae19
Date: 2012-09-04 15:26 +0200
http://bitbucket.org/cffi/cffi/changeset/41a7f979ae19/

Log:	Add ffi.CData and ffi.CType.

diff --git a/c/_cffi_backend.c b/c/_cffi_backend.c
--- a/c/_cffi_backend.c
+++ b/c/_cffi_backend.c
@@ -4105,6 +4105,12 @@
     return Py_None;
 }
 
+static PyObject *b__get_types(PyObject *self, PyObject *noarg)
+{
+    return PyTuple_Pack(2, (PyObject *)&CData_Type,
+                           (PyObject *)&CTypeDescr_Type);
+}
+
 /************************************************************/
 
 static char _testfunc0(char a, char b)
@@ -4322,6 +4328,7 @@
     {"buffer", b_buffer, METH_VARARGS},
     {"get_errno", b_get_errno, METH_NOARGS},
     {"set_errno", b_set_errno, METH_VARARGS},
+    {"_get_types", b__get_types, METH_NOARGS},
     {"_testfunc", b__testfunc, METH_VARARGS},
     {NULL,     NULL}    /* Sentinel */
 };
diff --git a/c/test_c.py b/c/test_c.py
--- a/c/test_c.py
+++ b/c/test_c.py
@@ -1,6 +1,6 @@
 import py
 from _cffi_backend import *
-from _cffi_backend import _getfields, _testfunc
+from _cffi_backend import _getfields, _testfunc, _get_types
 
 # ____________________________________________________________
 
@@ -2067,3 +2067,16 @@
     BStruct = new_struct_type("foo")
     complete_struct_or_union(BStruct, [('b', BInt, -1, 1)],
                              None, 5, 1)
+
+def test_CData_CType():
+    CData, CType = _get_types()
+    BChar = new_primitive_type("char")
+    BCharP = new_pointer_type(BChar)
+    nullchr = cast(BChar, 0)
+    chrref = newp(BCharP, None)
+    assert isinstance(nullchr, CData)
+    assert isinstance(chrref, CData)
+    assert not isinstance(BChar, CData)
+    assert not isinstance(nullchr, CType)
+    assert not isinstance(chrref, CType)
+    assert isinstance(BChar, CType)
diff --git a/cffi/api.py b/cffi/api.py
--- a/cffi/api.py
+++ b/cffi/api.py
@@ -69,6 +69,7 @@
         del self._cdefsources[:]
         #
         self.NULL = self.cast("void *", 0)
+        self.CData, self.CType = backend._get_types()
 
     def cdef(self, csource, override=False):
         """Parse the given C source.  This registers all declared functions,
diff --git a/cffi/backend_ctypes.py b/cffi/backend_ctypes.py
--- a/cffi/backend_ctypes.py
+++ b/cffi/backend_ctypes.py
@@ -10,7 +10,11 @@
     xrange = range
     bytechr = lambda num: bytes([num])
 
+class CTypesType(type):
+    pass
+
 class CTypesData(object):
+    __metaclass__ = CTypesType
     __slots__ = ['__weakref__']
 
     def __init__(self, *args):
@@ -285,6 +289,9 @@
     def set_ffi(self, ffi):
         self.ffi = ffi
 
+    def _get_types(self):
+        return CTypesData, CTypesType
+
     def nonstandard_integer_types(self):
         UNSIGNED = 0x1000
         result = {}
diff --git a/doc/source/index.rst b/doc/source/index.rst
--- a/doc/source/index.rst
+++ b/doc/source/index.rst
@@ -952,6 +952,13 @@
         assert ffi.typeof(ptr) is ffi.typeof("foo_t*")
         ...
 
+.. versionadded:: 0.4
+   ``ffi.CData, ffi.CType``: the Python type of the objects referred to
+   as ``<cdata>`` and ``<ctype>`` in the rest of this document.  Note
+   that some cdata objects may be actually of a subclass of
+   ``ffi.CData``, and similarly with ctype, so you should check with
+   ``if isinstance(x, ffi.CData)``.
+
 ``ffi.sizeof("C type" or cdata object)``: return the size of the
 argument in bytes.  The argument can be either a C type, or a cdata object,
 like in the equivalent ``sizeof`` operator in C.
diff --git a/testing/backend_tests.py b/testing/backend_tests.py
--- a/testing/backend_tests.py
+++ b/testing/backend_tests.py
@@ -1383,3 +1383,12 @@
         del q
         import gc; gc.collect(); gc.collect(); gc.collect()
         assert seen == [1]
+
+    def test_CData_CType(self):
+        ffi = FFI(backend=self.Backend())
+        assert isinstance(ffi.cast("int", 0), ffi.CData)
+        assert isinstance(ffi.new("int *"), ffi.CData)
+        assert not isinstance(ffi.typeof("int"), ffi.CData)
+        assert not isinstance(ffi.cast("int", 0), ffi.CType)
+        assert not isinstance(ffi.new("int *"), ffi.CType)
+        assert isinstance(ffi.typeof("int"), ffi.CType)
diff --git a/testing/test_cdata.py b/testing/test_cdata.py
--- a/testing/test_cdata.py
+++ b/testing/test_cdata.py
@@ -21,6 +21,8 @@
         return FakeType('ptr-to-%r' % (x,))
     def cast(self, x, y):
         return 'casted!'
+    def _get_types(self):
+        return "CData", "CType"
 
 
 class FakeType(object):
diff --git a/testing/test_parsing.py b/testing/test_parsing.py
--- a/testing/test_parsing.py
+++ b/testing/test_parsing.py
@@ -43,6 +43,8 @@
         return FakeType("<void>")
     def cast(self, x, y):
         return 'casted!'
+    def _get_types(self):
+        return "CData", "CType"
 
 class FakeType(object):
     def __init__(self, cdecl):


More information about the pypy-commit mailing list