[pypy-svn] pypy jitypes2: add support for getting FuncPtr given their address

antocuni commits-noreply at bitbucket.org
Thu Dec 30 17:59:06 CET 2010


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: jitypes2
Changeset: r40287:e97c6b7923b5
Date: 2010-12-30 17:58 +0100
http://bitbucket.org/pypy/pypy/changeset/e97c6b7923b5/

Log:	add support for getting FuncPtr given their address

diff --git a/pypy/module/_ffi/test/test__ffi.py b/pypy/module/_ffi/test/test__ffi.py
--- a/pypy/module/_ffi/test/test__ffi.py
+++ b/pypy/module/_ffi/test/test__ffi.py
@@ -85,6 +85,16 @@
         pow_addr = libm.getaddressindll('pow')
         assert pow_addr == self.pow_addr & (sys.maxint*2-1)
 
+    def test_func_fromaddr(self):
+        import sys
+        from _ffi import CDLL, types, FuncPtr
+        libm = CDLL(self.libm_name)
+        pow_addr = libm.getaddressindll('pow')
+        pow = FuncPtr.fromaddr(pow_addr, 'pow', [types.double, types.double],
+                               types.double)
+        assert pow(2, 3) == 8
+
+
     def test_int_args(self):
         """
             int sum_xy(int x, int y)

diff --git a/pypy/module/_ffi/interp_ffi.py b/pypy/module/_ffi/interp_ffi.py
--- a/pypy/module/_ffi/interp_ffi.py
+++ b/pypy/module/_ffi/interp_ffi.py
@@ -11,7 +11,7 @@
 from pypy.rlib import jit
 from pypy.rlib import libffi
 from pypy.rlib.rdynload import DLOpenError
-from pypy.rlib.rarithmetic import intmask
+from pypy.rlib.rarithmetic import intmask, r_uint
 
 class W_FFIType(Wrappable):
     def __init__(self, name, ffitype):
@@ -23,7 +23,6 @@
         return space.wrap('<ffi type %s>' % self.name)
 
 
-
 W_FFIType.typedef = TypeDef(
     'FFIType',
     __str__ = interp2app(W_FFIType.str),
@@ -47,6 +46,15 @@
     'types',
     **build_ffi_types())
 
+
+def unwrap_ffitype(space, w_argtype, allow_void=False):
+    res = space.interp_w(W_FFIType, w_argtype).ffitype
+    if res is libffi.types.void and not allow_void:
+        msg = 'void is not a valid argument type'
+        raise OperationError(space.w_TypeError, space.wrap(msg))
+    return res
+
+
 # ========================================================================
 
 class W_FuncPtr(Wrappable):
@@ -216,10 +224,21 @@
         """
         return space.wrap(rffi.cast(rffi.LONG, self.func.funcsym))
 
+ at unwrap_spec(ObjSpace, W_Root, r_uint, str, W_Root, W_Root)
+def descr_fromaddr(space, w_cls, addr, name, w_argtypes, w_restype):
+    argtypes = [unwrap_ffitype(space, w_argtype) for w_argtype in
+                space.listview(w_argtypes)]
+    restype = unwrap_ffitype(space, w_restype, allow_void=True)
+    addr = rffi.cast(rffi.VOIDP, addr)
+    func = libffi.Func(name, argtypes, restype, addr)
+    return W_FuncPtr(func)
+    
+
 W_FuncPtr.typedef = TypeDef(
-    'FuncPtr',
+    '_ffi.FuncPtr',
     __call__ = interp2app(W_FuncPtr.call),
     getaddr = interp2app(W_FuncPtr.getaddr),
+    fromaddr = interp2app(descr_fromaddr, as_classmethod=True)
     )
 
 
@@ -236,19 +255,11 @@
         self.name = name
         self.space = space
 
-    def ffitype(self, w_argtype, allow_void=False):
-        res = self.space.interp_w(W_FFIType, w_argtype).ffitype
-        if res is libffi.types.void and not allow_void:
-            space = self.space
-            msg = 'void is not a valid argument type'
-            raise OperationError(space.w_TypeError, space.wrap(msg))
-        return res
-
     @unwrap_spec('self', ObjSpace, str, W_Root, W_Root)
     def getfunc(self, space, name, w_argtypes, w_restype):
-        argtypes = [self.ffitype(w_argtype) for w_argtype in
+        argtypes = [unwrap_ffitype(space, w_argtype) for w_argtype in
                     space.listview(w_argtypes)]
-        restype = self.ffitype(w_restype, allow_void=True)
+        restype = unwrap_ffitype(space, w_restype, allow_void=True)
         try:
             func = self.cdll.getpointer(name, argtypes, restype)
         except KeyError:
@@ -274,7 +285,7 @@
 
 
 W_CDLL.typedef = TypeDef(
-    'CDLL',
+    '_ffi.CDLL',
     __new__     = interp2app(descr_new_cdll),
     getfunc     = interp2app(W_CDLL.getfunc),
     getaddressindll = interp2app(W_CDLL.getaddressindll),

diff --git a/pypy/module/_ffi/__init__.py b/pypy/module/_ffi/__init__.py
--- a/pypy/module/_ffi/__init__.py
+++ b/pypy/module/_ffi/__init__.py
@@ -4,8 +4,9 @@
 class Module(MixedModule):
 
     interpleveldefs = {
-        'CDLL'               : 'interp_ffi.W_CDLL',
-        'types':             'interp_ffi.W_types',
+        'CDLL':    'interp_ffi.W_CDLL',
+        'types':   'interp_ffi.W_types',
+        'FuncPtr': 'interp_ffi.W_FuncPtr'
     }
 
     appleveldefs = {}


More information about the Pypy-commit mailing list