[pypy-svn] r50578 - in pypy/branch/applevel-ctypes2/pypy/rlib: . test

arigo at codespeak.net arigo at codespeak.net
Mon Jan 14 11:20:53 CET 2008


Author: arigo
Date: Mon Jan 14 11:20:51 2008
New Revision: 50578

Modified:
   pypy/branch/applevel-ctypes2/pypy/rlib/libffi.py
   pypy/branch/applevel-ctypes2/pypy/rlib/test/test_libffi.py
Log:
(fijal, arigo)  Refactor libffi.py to add a lower-level
interface: RawFuncPtr.


Modified: pypy/branch/applevel-ctypes2/pypy/rlib/libffi.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/rlib/libffi.py	(original)
+++ pypy/branch/applevel-ctypes2/pypy/rlib/libffi.py	Mon Jan 14 11:20:51 2008
@@ -170,33 +170,60 @@
 def check_pointer_type(TP):
     pass
 
-class FuncPtr(object):
+class AbstractFuncPtr(object):
+    ll_cif = lltype.nullptr(FFI_CIFP.TO)
+    ll_argtypes = lltype.nullptr(FFI_TYPE_PP.TO)
+
     def __init__(self, name, argtypes, restype, funcsym):
-        # initialize each one of pointers with null
-        TP = rffi.CArray(rffi.VOIDP)
-        self.ll_args = lltype.nullptr(TP)
-        self.ll_cif = lltype.nullptr(FFI_CIFP.TO)
-        self.ll_argtypes = lltype.nullptr(FFI_TYPE_PP.TO)
-        self.ll_result = lltype.nullptr(rffi.VOIDP.TO)
         self.name = name
         self.argtypes = argtypes
         self.restype = restype
         self.funcsym = funcsym
         argnum = len(argtypes)
         self.argnum = argnum
-        self.pushed_args = 0
-        self.ll_args = lltype.malloc(TP, argnum, flavor='raw')
-        self.ll_cif = lltype.malloc(FFI_CIFP.TO, flavor='raw')
         self.ll_argtypes = lltype.malloc(FFI_TYPE_PP.TO, argnum, flavor='raw')
         for i in range(argnum):
             self.ll_argtypes[i] = argtypes[i]
         # XXX why cast to FFI_TYPE_PP is needed? ll2ctypes bug?
+        self.ll_cif = lltype.malloc(FFI_CIFP.TO, flavor='raw')
         res = c_ffi_prep_cif(self.ll_cif, FFI_DEFAULT_ABI,
                              rffi.cast(rffi.UINT, argnum), restype,
                              rffi.cast(FFI_TYPE_PP, self.ll_argtypes))
         if not res == FFI_OK:
             raise OSError(-1, "Wrong typedef")
-        for i in range(argnum):
+
+    def __del__(self):
+        if self.ll_cif:
+            lltype.free(self.ll_cif, flavor='raw')
+        if self.ll_argtypes:
+            lltype.free(self.ll_argtypes, flavor='raw')
+
+
+class RawFuncPtr(AbstractFuncPtr):
+
+    def call(self, args_ll, ll_result):
+        if len(args_ll) != self.argnum:
+            raise ValueError("wrong number of arguments in call to %s(): "
+                             "%d instead of %d" % (self.name,
+                                                   len(args_ll),
+                                                   self.argnum))
+        ll_args = lltype.malloc(rffi.VOIDPP.TO, len(args_ll), flavor='raw')
+        for i in range(len(args_ll)):
+            ll_args[i] = args_ll[i]
+        c_ffi_call(self.ll_cif, self.funcsym, ll_result, ll_args)
+        lltype.free(ll_args, flavor='raw')
+
+
+class FuncPtr(AbstractFuncPtr):
+    ll_args = lltype.nullptr(rffi.VOIDPP.TO)
+    ll_result = lltype.nullptr(rffi.VOIDP.TO)
+
+    def __init__(self, name, argtypes, restype, funcsym):
+        # initialize each one of pointers with null
+        AbstractFuncPtr.__init__(self, name, argtypes, restype, funcsym)
+        self.pushed_args = 0
+        self.ll_args = lltype.malloc(rffi.VOIDPP.TO, self.argnum, flavor='raw')
+        for i in range(self.argnum):
             # space for each argument
             self.ll_args[i] = lltype.malloc(rffi.VOIDP.TO,
                                             intmask(argtypes[i].c_size),
@@ -257,10 +284,7 @@
             lltype.free(self.ll_args, flavor='raw')
         if self.ll_result:
             lltype.free(self.ll_result, flavor='raw')
-        if self.ll_cif:
-            lltype.free(self.ll_cif, flavor='raw')
-        if self.ll_argtypes:
-            lltype.free(self.ll_argtypes, flavor='raw')
+        AbstractFuncPtr.__del__(self)
 
 class CDLL:
     def __init__(self, libname):
@@ -280,3 +304,7 @@
         # structures!
         return FuncPtr(name, argtypes, restype, dlsym(self.lib, name))
 
+    def getrawpointer(self, name, argtypes, restype):
+        # these arguments are already casted to proper ffi
+        # structures!
+        return RawFuncPtr(name, argtypes, restype, dlsym(self.lib, name))

Modified: pypy/branch/applevel-ctypes2/pypy/rlib/test/test_libffi.py
==============================================================================
--- pypy/branch/applevel-ctypes2/pypy/rlib/test/test_libffi.py	(original)
+++ pypy/branch/applevel-ctypes2/pypy/rlib/test/test_libffi.py	Mon Jan 14 11:20:51 2008
@@ -121,4 +121,19 @@
         res = fn(2.0, 4.0)
         assert res == 16.0
 
-        
+    def test_rawfuncptr(self):
+        libm = CDLL('libm.so')
+        pow = libm.getrawpointer('pow', [ffi_type_double, ffi_type_double],
+                                 ffi_type_double)
+        buffer = lltype.malloc(rffi.DOUBLEP.TO, 3, flavor='raw')
+        buffer[0] = 2.0
+        buffer[1] = 3.0
+        buffer[2] = 43.5
+        pow.call([rffi.cast(rffi.VOIDP, buffer),
+                  rffi.cast(rffi.VOIDP, rffi.ptradd(buffer, 1))],
+                 rffi.cast(rffi.VOIDP, rffi.ptradd(buffer, 2)))
+        assert buffer[2] == 8.0
+        lltype.free(buffer, flavor='raw')
+        del pow
+        del libm
+        assert len(ALLOCATED) == 1 # ffi_type_double get allocated



More information about the Pypy-commit mailing list