Commits

Armin Rigo committed ed71920

Write ffi.new(array) on ctypes.

Comments (0)

Files changed (5)

 
     def typeof(self, cdecl):
         typenode = self._parse_type(cdecl)
-        return self._get_type(typenode)
+        return self._get_btype(typenode)
+
+    def new(self, cdecl):
+        btype = self.typeof(cdecl)
+        return btype()
 
     def _parse_type(self, cdecl):
         parser = pycparser.CParser()
         typenode = ast.ext[0].type.args.params[0].type
         return typenode
 
-    def _get_type(self, typenode):
+    def _get_btype(self, typenode):
         if isinstance(typenode, pycparser.c_ast.ArrayDecl):
             # array type
             assert isinstance(typenode.dim, pycparser.c_ast.Constant), (
                 "non-constant array length")
             length = int(typenode.dim.value)
-            bitem = self._get_type(typenode.type)
+            bitem = self._get_btype(typenode.type)
             return self._get_cached_btype('new_array_type', bitem, length)
         else:
             # assume a primitive type
         if name in self._ffi._functions:
             node = self._ffi._functions[name]
             name = node.type.declname
-            args = [self._ffi._get_type(argdeclnode.type)
+            args = [self._ffi._get_btype(argdeclnode.type)
                     for argdeclnode in node.args.params]
-            result = self._ffi._get_type(node.type)
+            result = self._ffi._get_btype(node.type)
             value = self._backendlib.load_function(name, args, result)
             setattr(self, name, value)
             return value

ffi/backend_ctypes.py

 class CTypesBackend(object):
 
     PRIMITIVE_TYPES = {
+        'int': ctypes.c_int,
         'double': ctypes.c_double,
     }
 
     def new_primitive_type(self, name):
         return self.PRIMITIVE_TYPES[name]
 
+    def new_array_type(self, bitem, length):
+        ctype = bitem * length
+        #
+        class CTypesArray(object):
+            def __init__(self):
+                self._blob = ctype()
+            def __getitem__(self, index):
+                if not (0 <= index < length):
+                    raise IndexError
+                return self._blob[index]
+            def __setitem__(self, index, value):
+                if not (0 <= index < length):
+                    raise IndexError
+                self._blob[index] = value
+        #
+        return CTypesArray
+
 
 class CTypesLibrary(object):
 

testing/backend_tests.py

+import py
+from ffi import FFI
+
+
+class BackendTests:
+
+    def test_new_array_no_arg(self):
+        ffi = FFI(backend=self.Backend())
+        p = ffi.new("int[10]")
+        # the object was zero-initialized:
+        for i in range(10):
+            assert p[i] == 0
+
+    def test_array_indexing(self):
+        ffi = FFI(backend=self.Backend())
+        p = ffi.new("int[10]")
+        p[0] = 42
+        p[9] = 43
+        assert p[0] == 42
+        assert p[9] == 43
+        py.test.raises(IndexError, "p[10]")
+        py.test.raises(IndexError, "p[10] = 44")
+        py.test.raises(IndexError, "p[-1]")
+        py.test.raises(IndexError, "p[-1] = 44")

testing/test_cdata.py

-import py
 from ffi import FFI
 
 class FakeBackend(object):
     clong = ffi.typeof("long")
     assert isinstance(clong, FakePrimitiveType)
     assert clong.cdecl == 'long'
-
-def test_new_array_no_arg():
-    ffi = FFI(backend=FakeBackend())
-    p = ffi.new("int[10]")
-    # the object was zero-initialized:
-    for i in range(10):
-        assert p[i] == 0
-
-def test_array_indexing():
-    ffi = FFI(backend=FakeBackend())
-    p = ffi.new("int[10]")
-    p[0] = 42
-    p[9] = 43
-    assert p[0] == 42
-    assert p[9] == 43
-    py.test.raises(IndexError, "p[10]")
-    py.test.raises(IndexError, "p[10] = 44")
-    py.test.raises(IndexError, "p[-1]")
-    py.test.raises(IndexError, "p[-1] = 44")

testing/test_ctypes.py

+from testing import backend_tests
+from ffi.backend_ctypes import CTypesBackend
+
+
+class TestCTypes(backend_tests.BackendTests):
+    Backend = CTypesBackend