Commits

wlav committed c1bf38d

o) mixin for floats
o) combine common mixing parts for floats and integers
o) support for float default arguments on ffi path

  • Participants
  • Parent commits ba631eb
  • Branches reflex-support

Comments (0)

Files changed (5)

pypy/module/cppyy/converter.py

 from pypy.interpreter.error import OperationError
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rlib.rarithmetic import r_singlefloat
-from pypy.rlib import jit, libffi, clibffi
+from pypy.rlib import jit, libffi, clibffi, rfloat
 
 from pypy.module._rawffi.interp_rawffi import unpack_simple_shape
 from pypy.module._rawffi.array import W_Array
                                  space.wrap("raw buffer interface not supported"))
 
 
-class IntTypeConverterMixin(object):
+class NumericTypeConverterMixin(object):
     _mixin_ = True
     _immutable_ = True
 
-    def convert_argument(self, space, w_obj, address):
-        x = rffi.cast(self.rffiptype, address)
-        x[0] = self._unwrap_object(space, w_obj)
-
     def convert_argument_libffi(self, space, w_obj, argchain):
         argchain.arg(self._unwrap_object(space, w_obj))
 
         rffiptr = rffi.cast(self.rffiptype, address)
         rffiptr[0] = self._unwrap_object(space, w_value)
 
+class IntTypeConverterMixin(NumericTypeConverterMixin):
+    _mixin_ = True
+    _immutable_ = True
+
+    def convert_argument(self, space, w_obj, address):
+        x = rffi.cast(self.rffiptype, address)
+        x[0] = self._unwrap_object(space, w_obj)
+
+class FloatTypeConverterMixin(NumericTypeConverterMixin):
+    _mixin_ = True
+    _immutable_ = True
+
+    def convert_argument(self, space, w_obj, address):
+        x = rffi.cast(self.rffiptype, address)
+        x[0] = self._unwrap_object(space, w_obj)
+        typecode = rffi.cast(rffi.CCHARP,
+            _direct_ptradd(address, capi.c_function_arg_typeoffset()))
+        typecode[0] = self.typecode
+
 
 class VoidConverter(TypeConverter):
     _immutable_ = True
     def _unwrap_object(self, space, w_obj):
         return space.uint_w(w_obj)
 
-class FloatConverter(TypeConverter):
+
+class FloatConverter(FloatTypeConverterMixin, TypeConverter):
     _immutable_ = True
     libffitype = libffi.types.float
+    rffiptype = rffi.FLOATP
+    typecode = 'f'
+
+    def __init__(self, space, default):
+        if default:
+            fval = float(rfloat.rstring_to_float(default))
+        else:
+            fval = float(0.)
+        self.default = r_singlefloat(fval)
 
     def _unwrap_object(self, space, w_obj):
         return r_singlefloat(space.float_w(w_obj))
 
-    def convert_argument(self, space, w_obj, address):
-        x = rffi.cast(rffi.FLOATP, address)
-        x[0] = self._unwrap_object(space, w_obj)
-        typecode = rffi.cast(rffi.CCHARP,
-            _direct_ptradd(address, capi.c_function_arg_typeoffset()))
-        typecode[0] = 'f'
-
-    def convert_argument_libffi(self, space, w_obj, argchain):
-        from pypy.rlib.rarithmetic import r_singlefloat
-        fval = space.float_w(w_obj)
-        sfval = r_singlefloat(fval)
-        argchain.arg(sfval)
-
     def from_memory(self, space, w_obj, w_type, offset):
         address = self._get_raw_address(space, w_obj, offset)
-        floatptr = rffi.cast(rffi.FLOATP, address)
-        return space.wrap(float(floatptr[0]))
+        rffiptr = rffi.cast(self.rffiptype, address)
+        return space.wrap(float(rffiptr[0]))
 
-    def to_memory(self, space, w_obj, w_value, offset):
-        address = self._get_raw_address(space, w_obj, offset)
-        floatptr = rffi.cast(rffi.FLOATP, address)
-        floatptr[0] = self._unwrap_object(space, w_value)
-
-class DoubleConverter(TypeConverter):
+class DoubleConverter(FloatTypeConverterMixin, TypeConverter):
     _immutable_ = True
     libffitype = libffi.types.double
+    rffiptype = rffi.DOUBLEP
+    typecode = 'd'
+
+    def __init__(self, space, default):
+        if default:
+            self.default = rffi.cast(rffi.DOUBLE, rfloat.rstring_to_float(default))
+        else:
+            self.default = rffi.cast(rffi.DOUBLE, 0.)
 
     def _unwrap_object(self, space, w_obj):
         return space.float_w(w_obj)
 
-    def convert_argument(self, space, w_obj, address):
-        x = rffi.cast(rffi.DOUBLEP, address)
-        x[0] = self._unwrap_object(space, w_obj)
-        typecode = rffi.cast(rffi.CCHARP,
-            _direct_ptradd(address, capi.c_function_arg_typeoffset()))
-        typecode[0] = 'd'
-
-    def convert_argument_libffi(self, space, w_obj, argchain):
-        argchain.arg(self._unwrap_object(space, w_obj))
-
-    def from_memory(self, space, w_obj, w_type, offset):
-        address = self._get_raw_address(space, w_obj, offset)
-        doubleptr = rffi.cast(rffi.DOUBLEP, address)
-        return space.wrap(doubleptr[0])
-
-    def to_memory(self, space, w_obj, w_value, offset):
-        address = self._get_raw_address(space, w_obj, offset)
-        doubleptr = rffi.cast(rffi.DOUBLEP, address)
-        doubleptr[0] = self._unwrap_object(space, w_value)
-
 
 class CStringConverter(TypeConverter):
     _immutable_ = True

pypy/module/cppyy/interp_cppyy.py

+import pypy.module.cppyy.capi as capi
+
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef, interp_attrproperty
 from pypy.rlib import libffi, rdynload, rweakref
 from pypy.rlib import jit, debug
 
-from pypy.module.cppyy import converter, executor, helper, capi
+from pypy.module.cppyy import converter, executor, helper
 
 
 class FastCallNotPossible(Exception):
     pass
 
 def _direct_ptradd(ptr, offset):        # TODO: factor out with convert.py
+    assert lltype.typeOf(ptr) == capi.C_OBJECT
     address = rffi.cast(rffi.CCHARP, ptr)
     return rffi.cast(capi.C_OBJECT, lltype.direct_ptradd(address, offset))
 

pypy/module/cppyy/test/example01.cxx

 typeValueImp(long, long)
 typeValueImp(unsigned long, ulong)
 
+typeValueImp(float, float)
+typeValueImp(double, double)
+
 std::string ArgPasser::stringValue(std::string arg0, int argn, std::string arg1)
 {
    switch (argn) {

pypy/module/cppyy/test/example01.h

     int globalAddOneToInt(int a);
 }
 
-#define typeValue(itype, tname) \
+#define itypeValue(itype, tname) \
    itype tname##Value(itype arg0, int argn=0, itype arg1=1, itype arg2=2)
 
+#define ftypeValue(ftype) \
+   ftype ftype##Value(ftype arg0, int argn=0, ftype arg1=1., ftype arg2=2.)
+
 // argument passing
 class ArgPasser {        // use a class for now as methptrgetter not
 public:                  // implemented for global functions
-   typeValue(short, short);
-   typeValue(unsigned short, ushort);
-   typeValue(int, int);
-   typeValue(unsigned int, uint);
-   typeValue(long, long);
-   typeValue(unsigned long, ulong);
+   itypeValue(short, short);
+   itypeValue(unsigned short, ushort);
+   itypeValue(int, int);
+   itypeValue(unsigned int, uint);
+   itypeValue(long, long);
+   itypeValue(unsigned long, ulong);
+
+   ftypeValue(float);
+   ftypeValue(double);
 
    std::string stringValue(
       std::string arg0, int argn=0, std::string arg1 = "default");

pypy/module/cppyy/test/test_pythonify.py

             assert g(11, 2)         ==  2
             assert g(11)            == 11
 
-    def test12_underscore_in_class_name(self):
+        for ftype in ['float', 'double']:
+            g = getattr(a, '%sValue' % ftype)
+            raises(TypeError, 'g(1., 2, 3., 4., 6.)')
+            assert g(11., 0, 12., 13.) == 11.
+            assert g(11., 1, 12., 13.) == 12.
+            assert g(11., 1, 12.)      == 12.
+            assert g(11., 2, 12.)      ==  2.
+            assert g(11., 1)           ==  1.
+            assert g(11., 2)           ==  2.
+            assert g(11.)              == 11.
+
+    def test11_underscore_in_class_name(self):
         """Test recognition of '_' as part of a valid class name"""
 
         import cppyy