[pypy-svn] r47474 - in pypy/dist/pypy/rlib: . test

fijal at codespeak.net fijal at codespeak.net
Mon Oct 15 19:23:49 CEST 2007


Author: fijal
Date: Mon Oct 15 19:23:48 2007
New Revision: 47474

Modified:
   pypy/dist/pypy/rlib/libffi.py
   pypy/dist/pypy/rlib/test/test_libffi.py
Log:
Support for pointers.


Modified: pypy/dist/pypy/rlib/libffi.py
==============================================================================
--- pypy/dist/pypy/rlib/libffi.py	(original)
+++ pypy/dist/pypy/rlib/libffi.py	Mon Oct 15 19:23:48 2007
@@ -49,7 +49,10 @@
     return l
 
 base_names = ['double', 'uchar', 'schar', 'sshort', 'ushort', 'uint', 'sint',
-              'ulong', 'slong', 'float', 'pointer', 'void']
+              'ulong', 'slong', 'float', 'pointer', 'void',
+              # by size
+              'sint8', 'uint8', 'sint16', 'uint16', 'sint32', 'uint32',
+              'sint64', 'uint64']
 type_names = ['ffi_type_%s' % name for name in base_names]
 for i in type_names:
     add_simple_type(i)
@@ -149,6 +152,9 @@
     buf[0] = arg
 push_arg_as_ffiptr._annspecialcase_ = 'specialize:argtype(1)'
 
+def check_pointer_type(TP):
+    pass
+
 class FuncPtr(object):
     def __init__(self, name, argtypes, restype, funcsym):
         self.name = name
@@ -175,15 +181,24 @@
             self.ll_args[i] = lltype.malloc(rffi.VOIDP.TO,
                                             intmask(argtypes[i].c_size),
                                             flavor='raw')
-        self.ll_result = lltype.malloc(rffi.VOIDP.TO, intmask(restype.c_size),
-                                       flavor='raw')
+        if restype != ffi_type_void:
+            self.ll_result = lltype.malloc(rffi.VOIDP.TO,
+                                           intmask(restype.c_size),
+                                           flavor='raw')
 
-    # XXX some rpython trick to get rid of TP here?
     def push_arg(self, value):
         if self.pushed_args == self.argnum:
             raise TypeError("Too much arguments, eats %d, pushed %d" %
                             (self.argnum, self.argnum + 1))
         TP = lltype.typeOf(value)
+        if isinstance(TP, lltype.Ptr):
+            if TP.TO._gckind != 'raw':
+                raise ValueError("Can only push raw values to C, not 'gc'")
+            # XXX probably we should recursively check for struct fields
+            # here, lets just ignore that for now
+            if isinstance(TP.TO, lltype.Array) and not \
+                   TP.TO._hints.get('nolength', None):
+                raise ValueError("Can only push to C arrays without length info")
         push_arg_as_ffiptr(self.argtypes[self.pushed_args], TP, value,
                            self.ll_args[self.pushed_args])
         self.pushed_args += 1
@@ -214,7 +229,8 @@
         for i in range(argnum):
             lltype.free(self.ll_args[i], flavor='raw')
         lltype.free(self.ll_args, flavor='raw')
-        lltype.free(self.ll_result, flavor='raw')
+        if self.restype != ffi_type_void:
+            lltype.free(self.ll_result, flavor='raw')
         lltype.free(self.ll_cif, flavor='raw')
         lltype.free(self.ll_argtypes, flavor='raw')
 

Modified: pypy/dist/pypy/rlib/test/test_libffi.py
==============================================================================
--- pypy/dist/pypy/rlib/test/test_libffi.py	(original)
+++ pypy/dist/pypy/rlib/test/test_libffi.py	Mon Oct 15 19:23:48 2007
@@ -9,6 +9,7 @@
 from pypy.rpython.lltypesystem import rffi, lltype
 import os, sys
 import py
+import time
 
 def setup_module(mod):
     if not sys.platform.startswith('linux'):
@@ -18,10 +19,6 @@
     def setup_method(self, meth):
         ALLOCATED.clear()
 
-    def teardown_method(self, meth):
-        pass
-        #assert not ALLOCATED, not yet
-
     def test_dlopen(self):
         py.test.raises(OSError, "dlopen(rffi.str2charp('xxxxxxxxxxxx'))")
         assert dlopen(rffi.str2charp('/lib/libc.so.6'))
@@ -32,24 +29,30 @@
     def test_library_open(self):
         lib = self.get_libc()
         del lib
+        assert not ALLOCATED
 
     def test_library_get_func(self):
         lib = self.get_libc()
         ptr = lib.getpointer('time', [], ffi_type_void)
         py.test.raises(KeyError, lib.getpointer, 'xxxxxxxxxxxxxxx', [], ffi_type_void)
+        del ptr
         del lib
+        assert len(ALLOCATED) == 1
 
     def test_library_func_call(self):
         lib = self.get_libc()
         ptr = lib.getpointer('rand', [], ffi_type_sint)
         zeroes = 0
+        first = ptr.call(rffi.INT)
         for i in range(100):
             res = ptr.call(rffi.INT)
-            print res
-            if not res:
+            if res == first:
                 zeroes += 1
-        assert not zeroes
+        assert zeroes < 90
         # not very hard check, but something :]
+        del ptr
+        del lib
+        assert len(ALLOCATED) == 1 # ffi_type_sint get allocated
 
     def test_call_args(self):
         libm = CDLL('libm.so')
@@ -63,6 +66,42 @@
         pow.push_arg(3.0)
         res = pow.call(rffi.DOUBLE)
         assert res == 27.0
+        del pow
+        del libm
+        assert len(ALLOCATED) == 1
+
+    def test_wrong_args(self):
+        libc = CDLL('libc.so.6')
+        # XXX assume time_t is long
+        ctime = libc.getpointer('time', [ffi_type_pointer], ffi_type_ulong)
+        x = lltype.malloc(lltype.GcStruct('xxx'))
+        y = lltype.malloc(lltype.GcArray(rffi.LONG), 3)
+        z = lltype.malloc(lltype.Array(rffi.LONG), 4, flavor='raw')
+        py.test.raises(ValueError, "ctime.push_arg(x)")
+        py.test.raises(ValueError, "ctime.push_arg(y)")
+        py.test.raises(ValueError, "ctime.push_arg(z)")
+        del ctime
+        del libc
+        lltype.free(z, flavor='raw')
+        # allocation check makes no sense, since we've got GcStructs around
+
+    def test_call_time(self):
+        libc = CDLL('libc.so.6')
+        # XXX assume time_t is long
+        ctime = libc.getpointer('time', [ffi_type_pointer], ffi_type_ulong)
+        ctime.push_arg(lltype.nullptr(rffi.CArray(rffi.LONG)))
+        t0 = ctime.call(rffi.LONG)
+        time.sleep(2)
+        ctime.push_arg(lltype.nullptr(rffi.CArray(rffi.LONG)))
+        t1 = ctime.call(rffi.LONG)
+        assert t1 > t0
+        l_t = lltype.malloc(rffi.CArray(rffi.LONG), 1, flavor='raw')
+        ctime.push_arg(l_t)
+        t1 = ctime.call(rffi.LONG)
+        assert l_t[0] == t1
+        lltype.free(l_t, flavor='raw')
+        del ctime
+        assert len(ALLOCATED) == 1
 
     def test_compile(self):
         # XXX cannot run it on top of llinterp, some problems



More information about the Pypy-commit mailing list