[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