[pypy-svn] r76633 - in pypy/branch/fast-ctypes/pypy/module/_ctypes: . test

getxsick at codespeak.net getxsick at codespeak.net
Mon Aug 16 15:22:19 CEST 2010


Author: getxsick
Date: Mon Aug 16 15:22:18 2010
New Revision: 76633

Added:
   pypy/branch/fast-ctypes/pypy/module/_ctypes/interp_dll.py   (contents, props changed)
   pypy/branch/fast-ctypes/pypy/module/_ctypes/interp_test.py   (contents, props changed)
   pypy/branch/fast-ctypes/pypy/module/_ctypes/test/test_dll.py   (contents, props changed)
Modified:
   pypy/branch/fast-ctypes/pypy/module/_ctypes/   (props changed)
   pypy/branch/fast-ctypes/pypy/module/_ctypes/__init__.py   (contents, props changed)
   pypy/branch/fast-ctypes/pypy/module/_ctypes/test/   (props changed)
   pypy/branch/fast-ctypes/pypy/module/_ctypes/test/__init__.py   (props changed)
Log:
add dlopen function (it's equivalent to CDLL from module/jitffi)


Modified: pypy/branch/fast-ctypes/pypy/module/_ctypes/__init__.py
==============================================================================
--- pypy/branch/fast-ctypes/pypy/module/_ctypes/__init__.py	(original)
+++ pypy/branch/fast-ctypes/pypy/module/_ctypes/__init__.py	Mon Aug 16 15:22:18 2010
@@ -1,5 +1,8 @@
 from pypy.interpreter.mixedmodule import MixedModule
 
 class Module(MixedModule):
-    interpleveldefs = {}
+    interpleveldefs = {
+        'dlopen' : 'interp_dll.W_CDLL',
+        'Test'  : 'interp_test.W_Test',
+    }
     appleveldefs = {}

Added: pypy/branch/fast-ctypes/pypy/module/_ctypes/interp_dll.py
==============================================================================
--- (empty file)
+++ pypy/branch/fast-ctypes/pypy/module/_ctypes/interp_dll.py	Mon Aug 16 15:22:18 2010
@@ -0,0 +1,144 @@
+from pypy.rlib import rjitffi
+from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable
+from pypy.interpreter.error import OperationError, wrap_oserror
+from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.typedef import TypeDef
+
+class W_CDLL(Wrappable):
+    def __init__(self, space, name, mode=0):
+        # XXX mode is ignored
+        if name is None:
+            return space.w_None # XXX this should return *all* loaded libs, dlopen(NULL)
+        self.space = space
+        self.rcdll = rjitffi.CDLL(name, load=False)
+        try:
+            self.lib_w = W_LibHandler(self.space, name)
+        except OSError, e:
+            raise OperationError(space.w_OSError, space.wrap(str(e)))
+
+    def get_w(self, space, func, w_args_type, res_type='v'):
+        args_type_w = [ space.str_w(w_x)
+                        for w_x in space.listview(w_args_type) ]
+        try:
+            ret = W_Get(space, self.rcdll.cpu, self.lib_w,
+                        func, args_type_w, res_type)
+        except ValueError, e:
+            raise OperationError(space.w_ValueError, space.wrap(str(e)))
+        return space.wrap(ret)
+
+def W_CDLL___new__(space, w_type, name, mode=0):
+    try:
+        return space.wrap(W_CDLL(space, name, mode))
+    except OSError, e:
+        raise wrap_oserror(space, e)
+
+W_CDLL.typedef = TypeDef(
+        'CDLL',
+        __new__ = interp2app(W_CDLL___new__,
+                             unwrap_spec=[ObjSpace, W_Root, str, int]),
+        get     = interp2app(W_CDLL.get_w,
+                             unwrap_spec=['self', ObjSpace, str, W_Root, str]),
+        __doc__ = """ C Dynamically loaded library
+use CDLL(libname) to create a handle to a C library (the argument is processed
+the same way as dlopen processes it)."""
+)
+
+
+class W_LibHandler(Wrappable):
+    def __init__(self, space, name):
+        self.space = space
+        try:
+            self.rlibhandler = rjitffi._LibHandler(name)
+        except OSError, e:
+            raise OperationError(space.w_OSError, space.wrap(str(e)))
+        self.handler = self.rlibhandler.handler
+
+def W_LibHandler___new__(space, w_type, name):
+    try:
+        return space.wrap(W_LibHandler(space, name))
+    except OSError, e:
+        raise wrap_oserror(space, e)
+
+W_LibHandler.typedef = TypeDef(
+        'LibHandler',
+        __new__ = interp2app(W_LibHandler___new__, unwrap_spec=[ObjSpace,
+                                                                W_Root, str])
+)
+
+class Cache(object):
+    def __init__(self, space):
+        self.cache = {}
+
+class W_Get(Wrappable):
+    def __init__(self, space, cpu, lib, func, args_type, res_type='v'):
+        self.space = space
+
+        wrap_func = (self.wrap_int_w, self.wrap_float_w,
+                     self.wrap_ref_w, self.wrap_void_w)
+        self.rget = rjitffi._Get(cpu, lib, func, args_type, res_type,
+                                 wrap_func, cache=True)
+
+        # grab from the cache if possible
+        arg_classes = ''.join(args_type)
+        key = (res_type, arg_classes)
+        cache = space.fromcache(Cache).cache
+        try:
+            self.rget.looptoken = cache[key]
+        except KeyError:
+            self.rget.gen_looptaken()
+            cache[key] = self.rget.looptoken
+
+    def call_w(self, space, w_args=None):
+        if not space.is_w(w_args, space.w_None):
+            i = 0
+            w_iterator = space.iter(w_args)
+            while True:
+                try:
+                    w_arg = space.next(w_iterator)
+                except OperationError, e:
+                    if not e.match(space, space.w_StopIteration):
+                        raise
+                    break # done
+
+                if self.rget.args_type[i] == 'i':
+                    self.rget.push_int(space.int_w(w_arg))
+                elif self.rget.args_type[i] == 'f':
+                    self.rget.push_float(space.float_w(w_arg))
+                elif self.rget.args_type[i] == 'p':
+                    self.rget.push_ref(space.int_w(w_arg))
+                else:
+                    # should never happen (raised earlier)
+                    raise OperationError(
+                            space.w_ValueError,
+                            space.wrap('Unsupported type of argument: %s'
+                                        % self.rget.args_type[0]))
+                i += 1
+        return self.rget.call()
+
+    def wrap_int_w(self, value):
+        return self.space.wrap(value)
+
+    def wrap_float_w(self, value):
+        return self.space.wrap(value)
+
+    def wrap_ref_w(self, value):
+        return self.space.wrap(value)
+
+    def wrap_void_w(self, w_value):
+        return w_value
+
+#def W_Get___new__(space, w_type, cpu, lib, func, args_type, res_type):
+#    try:
+#        return space.wrap(W_Get(space, w_type, cpu, lib, func, args_type, res_type))
+#    except OSError, e:
+#        raise wrap_oserror(space, e)
+
+W_Get.typedef = TypeDef(
+        'Get',
+        #__new__ = interp2app(W_Get___new__, unwrap_spec=[ObjSpace, W_Root, W_Root, W_Root, str, W_Root, str]),
+        call = interp2app(W_Get.call_w, unwrap_spec=['self', ObjSpace, W_Root]),
+        wrap_int = interp2app(W_Get.wrap_int_w, unwrap_spec=['self', int]),
+        wrap_float = interp2app(W_Get.wrap_float_w, unwrap_spec=['self', float]),
+        wrap_ref = interp2app(W_Get.wrap_ref_w, unwrap_spec=['self', int]),
+        wrap_void = interp2app(W_Get.wrap_void_w, unwrap_spec=['self', W_Root])
+)

Added: pypy/branch/fast-ctypes/pypy/module/_ctypes/interp_test.py
==============================================================================
--- (empty file)
+++ pypy/branch/fast-ctypes/pypy/module/_ctypes/interp_test.py	Mon Aug 16 15:22:18 2010
@@ -0,0 +1,45 @@
+from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable
+from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.typedef import TypeDef
+from pypy.rpython.lltypesystem import rffi, lltype
+
+# for tests only
+class W_Test(Wrappable):
+    def __init__(self, space):
+        self.space = space
+
+    def get_intp_w(self, space, n, w_values):
+        values_w = [ space.int_w(w_x) for w_x in space.listview(w_values) ]
+        intp = lltype.malloc(rffi.INTP.TO, n, flavor='raw') # XXX free it!
+        for i in xrange(n):
+            intp[i] = values_w[i]
+        return space.wrap(rffi.cast(lltype.Signed, intp))
+
+    def get_charp_w(self, space, txt):
+        charp = rffi.str2charp(txt)
+        return space.wrap(rffi.cast(lltype.Signed, charp)) # XXX free it!
+
+    def get_str_w(self, space, addr):
+        charp = rffi.cast(rffi.CCHARP, addr)
+        return space.wrap(rffi.charp2str(charp)) # XXX free it?
+
+    def get_int_from_addr_w(self, space, addr):
+        intp = rffi.cast(rffi.INTP, addr)
+        return space.wrap(intp[0]) # return the first element
+
+def W_Test___new__(space, w_x):
+    return space.wrap(W_Test(space))
+
+W_Test.typedef = TypeDef(
+        'Test',
+        __new__ = interp2app(W_Test___new__, unwrap_spec=[ObjSpace, W_Root]),
+        get_intp = interp2app(W_Test.get_intp_w,
+                              unwrap_spec=['self', ObjSpace, int, W_Root]),
+        get_charp = interp2app(W_Test.get_charp_w,
+                              unwrap_spec=['self', ObjSpace, str]),
+        get_str = interp2app(W_Test.get_str_w,
+                              unwrap_spec=['self', ObjSpace, int]),
+        get_int_from_addr = interp2app(W_Test.get_int_from_addr_w,
+                                 unwrap_spec=['self', ObjSpace, int])
+)
+

Added: pypy/branch/fast-ctypes/pypy/module/_ctypes/test/test_dll.py
==============================================================================
--- (empty file)
+++ pypy/branch/fast-ctypes/pypy/module/_ctypes/test/test_dll.py	Mon Aug 16 15:22:18 2010
@@ -0,0 +1,178 @@
+from pypy.conftest import gettestobjspace
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
+from pypy.translator.platform import platform
+
+import py
+
+class AppTestJitffi(object):
+    @staticmethod
+    def preprare_c_example():
+        from pypy.tool.udir import udir
+        c_file = udir.ensure("test_ctypes", dir=True).join("xlib.c")
+        c_file.write(py.code.Source('''
+        int add_integers(int a, int b)
+        {
+           return a+b;
+        }
+
+        double add_floats(double a, double b)
+        {
+           return a+b;
+        }
+
+        int add_intfloat(int a, double b)
+        {
+           int rb = (int)b;
+           return a+rb;
+        }
+
+        double return_float(int a, int b)
+        {
+           return a+b;
+        }
+
+        int max3(int a, int b, int c)
+        {
+           int max = a;
+           if (b > max) max = b;
+           if (c > max) max = c;
+           return max;
+        }
+
+        int fvoid(void)
+        {
+           return 1;
+        }
+
+        void return_void(int a, int b)
+        {
+            int c;
+            c = a + b;
+        }
+        int return_ptrvalue(int a, int *b)
+        {
+            return a+(*b);
+        }
+        int sum_intarray(int *a)
+        {
+            int i;
+            int sum = 0;
+            for(i=0; i<5; i++)
+            {
+                sum += *a+i;
+            }
+            return sum;
+        }
+        void a2b(char *txt)
+        {
+            int i;
+            for(i=0; txt[i] != '\0'; i++)
+            {
+                if (txt[i] == 'a') txt[i] = 'b';
+            }
+        }
+        int *return_intptr(int a)
+        {
+            int *x = malloc(sizeof(int));
+            *x = a;
+            return x;
+        }
+        '''
+        ))
+
+        symbols = ['add_integers', 'add_floats', 'add_intfloat',
+                   'return_float', 'max3', 'fvoid', 'return_void',
+                   'return_ptrvalue', 'sum_intarray', 'a2b', 'return_intptr']
+        eci = ExternalCompilationInfo(export_symbols=symbols)
+
+        return str(platform.compile([c_file], eci, 'x', standalone=False))
+
+    def setup_class(cls):
+        space = gettestobjspace(usemodules=('_ctypes',))
+        cls.space = space
+        cls.w_lib_name = space.wrap(cls.preprare_c_example())
+
+    def test_missing_lib(self):
+        from _ctypes import dlopen
+        raises(OSError, dlopen, 'xxxfoo888baryyy')
+
+    def test_get(self):
+        from _ctypes import dlopen
+        lib = dlopen(self.lib_name)
+
+        func = lib.get('add_integers', ['i', 'i'], 'i')
+        assert 3 == func.call([1,2])
+        func = lib.get('add_integers', ['i', 'i'], 'i')
+        assert 1 == func.call([-1,2])
+        func = lib.get('add_integers', ['i', 'i'], 'i')
+        assert 0 == func.call([0,0])
+
+        func = lib.get('max3', ['i', 'i', 'i'], 'i')
+        assert 8 == func.call([2, 8, 3])
+
+        func = lib.get('add_floats', ['f', 'f'], 'f')
+        assert 2.7 == func.call([1.2, 1.5])
+
+    def test_get_void(self):
+        from _ctypes import dlopen
+        lib = dlopen(self.lib_name)
+
+        func = lib.get('fvoid', [], 'i')
+        assert 1 == func.call()
+
+        func = lib.get('return_void', ['i', 'i'], 'v')
+        assert func.call([1, 2]) is None
+        func = lib.get('return_void', ['i', 'i'])
+        assert func.call([1, 2]) is None
+
+    def test_various_type_args(self):
+        from _ctypes import dlopen
+        lib = dlopen(self.lib_name)
+
+        func = lib.get('add_intfloat', ['i', 'f'], 'i')
+        assert func.call([1, 2.9]) == 3
+        assert func.call([0, 1.3]) == 1
+
+    def test_ptrargs(self):
+        from _ctypes import dlopen, Test
+        t = Test()
+        lib = dlopen(self.lib_name)
+
+        func = lib.get('return_ptrvalue', ['i', 'p'], 'i')
+        intp = t.get_intp(1, [10])
+        assert func.call([20, intp]) == 30
+
+        func = lib.get('sum_intarray', ['p'], 'i')
+        intp = t.get_intp(5, [ i for i in xrange(5) ])
+        assert func.call([intp]) == 10
+
+        func = lib.get('a2b', ['p'])
+        charp = t.get_charp('xaxaxa')
+        func.call([charp])
+        assert t.get_str(charp) == 'xbxbxb'
+
+    def test_get_ptr(self):
+        from _ctypes import dlopen, Test
+        t = Test()
+        lib = dlopen(self.lib_name)
+
+        func = lib.get('return_intptr', ['i'], 'p')
+        addr = func.call([22])
+        ret = t.get_int_from_addr(addr)
+        assert ret == 22
+
+    def test_undefined_func(self):
+        from _ctypes import dlopen
+        lib = dlopen(self.lib_name)
+        # xxxfoo888baryyy - not existed function
+        raises(ValueError, lib.get, 'xxxfoo888baryyy', [])
+        raises(ValueError, lib.get, 'xxxfoo888baryyy', ['i'], 'i')
+
+    def test_unknown_types(self):
+        from _ctypes import dlopen
+        lib = dlopen(self.lib_name)
+        # xxxfoo888baryyy - not defined types (args_type, res_type etc.)
+        raises(ValueError, lib.get, 'fvoid', ['xxxfoo888baryyy'])
+        raises(ValueError, lib.get, 'fvoid', ['i','xxxfoo888baryyy'])
+        raises(ValueError, lib.get, 'fvoid', ['xxxfoo888baryyy'],'i')
+        raises(ValueError, lib.get, 'fvoid', [], 'xxxfoo888baryyy')



More information about the Pypy-commit mailing list