Commits

Armin Rigo committed 2dc1641

(antocuni around, arigo) Start on simple arrays.

  • Participants
  • Parent commits e268a06

Comments (0)

Files changed (3)

src/backend_ctypes.py

-import ctypes
+import ctypes, ctypes.util
 
 
 class CTypesBackend(object):
         'double': ctypes.c_double,
     }
 
-    def load_library(self, name):
-        cdll = ctypes.CDLL('lib%s.so' % name)
+    def load_library(self, name=Ellipsis):
+        if name is Ellipsis:
+            name = 'c'    # on Posix only
+        path = ctypes.util.find_library(name)
+        cdll = ctypes.CDLL(path)
         return CTypesLibrary(cdll)
 
     def new_primitive_type(self, name):
 
 class FFI(object):
     
-    def __init__(self, backend):
+    def __init__(self, backend=None):
+        if backend is None:
+            import backend_ctypes
+            backend = backend_ctypes.CTypesBackend()
         self._backend = backend
         self._functions = {}
         self._primitive_types = {}
+        self.C = FFILibrary(self, self._backend.load_library())
 
     def cdef(self, csource):
         parser = pycparser.CParser()
         v.visit(ast)
 
     def load(self, name):
+        assert isinstance(name, str)
         return FFILibrary(self, self._backend.load_library(name))
 
     def _get_type(self, typenode):
-        # assume a primitive type
-        ident = ' '.join(typenode.type.names)
-        if ident not in self._primitive_types:
-            btype = self._backend.new_primitive_type(ident)
-            self._primitive_types[ident] = btype
-        return self._primitive_types[ident]
+        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)
+            return self._backend.new_array_type(bitem, length)
+        else:
+            # assume a primitive type
+            ident = ' '.join(typenode.type.names)
+            if ident not in self._primitive_types:
+                btype = self._backend.new_primitive_type(ident)
+                self._primitive_types[ident] = btype
+            return self._primitive_types[ident]
 
 
 class FFILibrary(object):

src/test/test_parsing.py

 
 class FakeBackend(object):
     
-    def load_library(self, name):
-        assert name == "foobar"
+    def load_library(self, name=Ellipsis):
+        assert name in [Ellipsis, "foobar"]
         return FakeLibrary()
 
     def new_primitive_type(self, name):
         return '<%s>' % name
 
+    def new_array_type(self, itemtype, length):
+        return '<array[%d] of %s>' % (length, itemtype)
+
 class FakeLibrary(object):
     
     def load_function(self, name, args, result):
     assert func.name == 'sin'
     assert func.args == ['<double>']
     assert func.result == '<double>'
+
+def test_pipe():
+    ffi = FFI(backend=FakeBackend())
+    ffi.cdef("int pipe(int pipefd[2]);")
+    func = ffi.C.pipe
+    assert func.name == 'pipe'
+    assert func.args == ['<array[2] of <int>>']
+    assert func.result == '<int>'