[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