[pypy-svn] r47309 - in pypy/dist/pypy/rlib: . test
fijal at codespeak.net
fijal at codespeak.net
Mon Oct 8 20:30:24 CEST 2007
Author: fijal
Date: Mon Oct 8 20:30:23 2007
New Revision: 47309
Modified:
pypy/dist/pypy/rlib/libffi.py
pypy/dist/pypy/rlib/test/test_libffi.py
Log:
Calling pow via libffi via wrapper works!
Modified: pypy/dist/pypy/rlib/libffi.py
==============================================================================
--- pypy/dist/pypy/rlib/libffi.py (original)
+++ pypy/dist/pypy/rlib/libffi.py Mon Oct 8 20:30:23 2007
@@ -60,6 +60,24 @@
for name in type_names:
locals()[name] = configure_simple_type(name)
+TYPE_MAP = {
+ rffi.DOUBLE : ffi_type_double,
+ rffi.FLOAT : ffi_type_float,
+ rffi.UCHAR : ffi_type_uchar,
+ rffi.CHAR : ffi_type_schar,
+ rffi.SHORT : ffi_type_sshort,
+ rffi.USHORT : ffi_type_ushort,
+ rffi.UINT : ffi_type_uint,
+ rffi.INT : ffi_type_sint,
+ rffi.ULONG : ffi_type_ulong,
+ rffi.LONG : ffi_type_slong,
+ lltype.Void : ffi_type_void,
+ # some shortcuts
+ None : ffi_type_void,
+ float : ffi_type_double,
+ int : ffi_type_sint,
+ }
+
def external(name, args, result):
return rffi.llexternal(name, args, result, includes=includes,
libraries=['dl', 'ffi'])
@@ -76,10 +94,12 @@
FFI_DEFAULT_ABI = rffi.cast(rffi.USHORT, cConfig.FFI_DEFAULT_ABI)
FFI_CIFP = rffi.COpaquePtr('ffi_cif', includes=includes)
+VOIDPP = rffi.CArrayPtr(rffi.VOIDP)
+
c_ffi_prep_cif = external('ffi_prep_cif', [FFI_CIFP, rffi.USHORT, rffi.UINT,
FFI_TYPE_P, FFI_TYPE_PP], rffi.INT)
c_ffi_call = external('ffi_call', [FFI_CIFP, rffi.VOIDP, rffi.VOIDP,
- rffi.CArrayPtr(rffi.VOIDP)], lltype.Void)
+ VOIDPP], lltype.Void)
def dlerror():
# XXX this would never work on top of ll2ctypes, because
@@ -112,30 +132,55 @@
return res
class FuncPtr:
- def __init__(self, func_sym):
- # xxx args here
+ def __init__(self, func_sym, argtypes, restype):
+ argnum = len(argtypes)
+ TP = rffi.CFixedArray(FFI_TYPE_P, argnum)
+ self.ll_argtypes = lltype.malloc(TP, flavor='raw')
+ self.argtypes = argtypes
+ for i, argtype in enumerate(argtypes):
+ self.ll_argtypes[i] = TYPE_MAP[argtype]
+ TP = rffi.CFixedArray(rffi.VOIDP, argnum)
+ self.ll_args = lltype.malloc(TP, flavor='raw')
+ for i in range(argnum):
+ # XXX
+ TP = rffi.CFixedArray(argtypes[i], 1)
+ self.ll_args[i] = rffi.cast(rffi.VOIDP,
+ lltype.malloc(TP, flavor='raw'))
+ self.restype = restype
+ if restype is not None:
+ TP = rffi.CFixedArray(restype, 1)
+ self.ll_res = lltype.malloc(TP, flavor='raw')
if not func_sym:
raise OSError("NULL func_sym")
self.func_sym = func_sym
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, 0),
- ffi_type_sint, lltype.nullptr(FFI_TYPE_PP.TO))
+ rffi.cast(rffi.UINT, argnum),
+ TYPE_MAP[restype],
+ rffi.cast(FFI_TYPE_PP, self.ll_argtypes))
if not res == FFI_OK:
raise OSError("Wrong typedef")
+ __init__._annspecialcase_ = 'specialize:arg(2, 3)'
def call(self, args):
# allocated result should be padded and stuff
PTR_T = lltype.Ptr(rffi.CFixedArray(rffi.INT, 1))
- result = lltype.malloc(PTR_T.TO, flavor='raw')
- c_ffi_call(self.ll_cif, self.func_sym, rffi.cast(rffi.VOIDP, result),
- lltype.nullptr(rffi.CCHARPP.TO))
- res = result[0]
- lltype.free(result, flavor='raw')
- return res
+ for i in range(len(args)):
+ TP = lltype.Ptr(rffi.CFixedArray(self.argtypes[i], 1))
+ addr = rffi.cast(TP, self.ll_args[i])
+ addr[0] = args[i]
+ c_ffi_call(self.ll_cif, self.func_sym,
+ rffi.cast(rffi.VOIDP, self.ll_res),
+ rffi.cast(VOIDPP, self.ll_args))
+ return self.ll_res[0]
+ call._annspecialcase_ = 'specialize:argtype(1)'
def __del__(self):
+ lltype.free(self.ll_argtypes, flavor='raw')
+ lltype.free(self.ll_args, flavor='raw')
lltype.free(self.ll_cif, flavor='raw')
+ if self.restype is not None:
+ lltype.free(self.ll_res, flavor='raw')
class CDLL:
def __init__(self, libname):
@@ -144,5 +189,5 @@
def __del__(self):
c_dlclose(self.lib)
- def getpointer(self, name):
- return FuncPtr(dlsym(self.lib, name))
+ def getpointer(self, name, argtypes, restype):
+ return FuncPtr(dlsym(self.lib, name), argtypes, restype)
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 8 20:30:23 2007
@@ -5,6 +5,7 @@
from pypy.rpython.test.test_llinterp import interpret
from pypy.rlib.libffi import CDLL, dlopen
from pypy.rpython.lltypesystem.ll2ctypes import ALLOCATED
+from pypy.rpython.lltypesystem import rffi
import os, sys
import py
@@ -33,13 +34,13 @@
def test_library_get_func(self):
lib = self.get_libc()
- ptr = lib.getpointer('time')
- py.test.raises(KeyError, lib.getpointer, 'xxxxxxxxxxxxxxx')
+ ptr = lib.getpointer('time', [], None)
+ py.test.raises(KeyError, lib.getpointer, 'xxxxxxxxxxxxxxx', [], None)
del lib
def test_library_func_call(self):
lib = self.get_libc()
- ptr = lib.getpointer('rand')
+ ptr = lib.getpointer('rand', [], rffi.INT)
zeroes = 0
for i in range(100):
res = ptr.call([])
@@ -47,3 +48,9 @@
zeroes += 1
assert not zeroes
# not very hard check, but something :]
+
+ def test_call_args(self):
+ libm = CDLL('libm.so')
+ pow = libm.getpointer('pow', [rffi.DOUBLE, rffi.DOUBLE], rffi.DOUBLE)
+ assert pow.call((2.0, 2.0)) == 4.0
+ assert pow.call((3.0, 3.0)) == 27.0
More information about the Pypy-commit
mailing list