Commits

Armin Rigo committed 41a7f97

Add ffi.CData and ffi.CType.

  • Participants
  • Parent commits 7a9c8bd

Comments (0)

Files changed (8)

File c/_cffi_backend.c

     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)
     {"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 */
 };
 import py
 from _cffi_backend import *
-from _cffi_backend import _getfields, _testfunc
+from _cffi_backend import _getfields, _testfunc, _get_types
 
 # ____________________________________________________________
 
     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)
         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,

File cffi/backend_ctypes.py

     xrange = range
     bytechr = lambda num: bytes([num])
 
+class CTypesType(type):
+    pass
+
 class CTypesData(object):
+    __metaclass__ = CTypesType
     __slots__ = ['__weakref__']
 
     def __init__(self, *args):
     def set_ffi(self, ffi):
         self.ffi = ffi
 
+    def _get_types(self):
+        return CTypesData, CTypesType
+
     def nonstandard_integer_types(self):
         UNSIGNED = 0x1000
         result = {}

File doc/source/index.rst

         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.

File testing/backend_tests.py

         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)

File testing/test_cdata.py

         return FakeType('ptr-to-%r' % (x,))
     def cast(self, x, y):
         return 'casted!'
+    def _get_types(self):
+        return "CData", "CType"
 
 
 class FakeType(object):

File testing/test_parsing.py

         return FakeType("<void>")
     def cast(self, x, y):
         return 'casted!'
+    def _get_types(self):
+        return "CData", "CType"
 
 class FakeType(object):
     def __init__(self, cdecl):