Author: Wim Lavrijsen <wlavrij...@lbl.gov> Branch: cling-support Changeset: r89032:026bbdbd61f5 Date: 2016-12-09 14:49 -0800 http://bitbucket.org/pypy/pypy/changeset/026bbdbd61f5/
Log: support signed char and long double in as much that rffi supports them diff --git a/pypy/module/cppyy/capi/builtin_capi.py b/pypy/module/cppyy/capi/builtin_capi.py --- a/pypy/module/cppyy/capi/builtin_capi.py +++ b/pypy/module/cppyy/capi/builtin_capi.py @@ -146,6 +146,13 @@ compilation_info=backend.eci) def c_call_d(space, cppmethod, cppobject, nargs, args): return _c_call_d(cppmethod, cppobject, nargs, args) +_c_call_ld = rffi.llexternal( + "cppyy_call_ld", + [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.LONGDOUBLE, + releasegil=ts_call, + compilation_info=backend.eci) +def c_call_ld(space, cppmethod, cppobject, nargs, args): + return _c_call_ld(cppmethod, cppobject, nargs, args) _c_call_r = rffi.llexternal( "cppyy_call_r", diff --git a/pypy/module/cppyy/capi/loadable_capi.py b/pypy/module/cppyy/capi/loadable_capi.py --- a/pypy/module/cppyy/capi/loadable_capi.py +++ b/pypy/module/cppyy/capi/loadable_capi.py @@ -125,23 +125,24 @@ # types (see capi/__init__.py), but by using strings here, that isn't guaranteed c_opaque_ptr = state.c_ulong - c_scope = c_opaque_ptr - c_type = c_scope - c_object = c_opaque_ptr - c_method = c_opaque_ptr - c_index = state.c_long + c_scope = c_opaque_ptr + c_type = c_scope + c_object = c_opaque_ptr + c_method = c_opaque_ptr + c_index = state.c_long c_index_array = state.c_voidp - c_void = state.c_void - c_char = state.c_char - c_uchar = state.c_uchar - c_short = state.c_short - c_int = state.c_int - c_long = state.c_long - c_llong = state.c_llong - c_ullong = state.c_ullong - c_float = state.c_float - c_double = state.c_double + c_void = state.c_void + c_char = state.c_char + c_uchar = state.c_uchar + c_short = state.c_short + c_int = state.c_int + c_long = state.c_long + c_llong = state.c_llong + c_ullong = state.c_ullong + c_float = state.c_float + c_double = state.c_double + c_ldouble = state.c_ldouble c_ccharp = state.c_ccharp c_voidp = state.c_voidp @@ -174,6 +175,7 @@ 'call_ll' : ([c_method, c_object, c_int, c_voidp], c_llong), 'call_f' : ([c_method, c_object, c_int, c_voidp], c_float), 'call_d' : ([c_method, c_object, c_int, c_voidp], c_double), + 'call_ld' : ([c_method, c_object, c_int, c_voidp], c_ldouble), 'call_r' : ([c_method, c_object, c_int, c_voidp], c_voidp), # call_s actually takes an size_t* as last parameter, but this will do @@ -372,6 +374,9 @@ def c_call_d(space, cppmethod, cppobject, nargs, cargs): args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)] return rffi.cast(rffi.DOUBLE, space.float_w(call_capi(space, 'call_d', args))) +def c_call_ld(space, cppmethod, cppobject, nargs, cargs): + args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)] + return rffi.cast(rffi.LONGDOUBLE, space.float_w(call_capi(space, 'call_ld', args))) def c_call_r(space, cppmethod, cppobject, nargs, cargs): args = [_ArgH(cppmethod), _ArgH(cppobject), _ArgL(nargs), _ArgP(cargs)] diff --git a/pypy/module/cppyy/converter.py b/pypy/module/cppyy/converter.py --- a/pypy/module/cppyy/converter.py +++ b/pypy/module/cppyy/converter.py @@ -3,7 +3,7 @@ from pypy.interpreter.error import OperationError, oefmt from rpython.rtyper.lltypesystem import rffi, lltype -from rpython.rlib.rarithmetic import r_singlefloat +from rpython.rlib.rarithmetic import r_singlefloat, r_longfloat from rpython.rlib import rfloat from pypy.module._rawffi.interp_rawffi import letter2tp @@ -351,7 +351,7 @@ def from_memory(self, space, w_obj, w_pycppclass, offset): address = self._get_raw_address(space, w_obj, offset) rffiptr = rffi.cast(self.c_ptrtype, address) - return space.wrap(float(rffiptr[0])) + return self._wrap_object(space, rffiptr[0]) class ConstFloatRefConverter(FloatConverter): _immutable_fields_ = ['typecode'] @@ -378,6 +378,25 @@ _immutable_fields_ = ['typecode'] typecode = 'd' +class LongDoubleConverter(ffitypes.typeid(rffi.LONGDOUBLE), FloatTypeConverterMixin, TypeConverter): + _immutable_fields_ = ['default'] + + def __init__(self, space, default): + if default: + fval = float(rfloat.rstring_to_float(default)) + else: + fval = float(0.) + self.default = r_longfloat(fval) + + def from_memory(self, space, w_obj, w_pycppclass, offset): + address = self._get_raw_address(space, w_obj, offset) + rffiptr = rffi.cast(self.c_ptrtype, address) + return self._wrap_object(space, rffiptr[0]) + +class ConstLongDoubleRefConverter(ConstRefNumericTypeConverterMixin, LongDoubleConverter): + _immutable_fields_ = ['typecode'] + typecode = 'g' + class CStringConverter(TypeConverter): def convert_argument(self, space, w_obj, address, call_local): x = rffi.cast(rffi.LONGP, address) @@ -725,6 +744,8 @@ _converters["const float&"] = ConstFloatRefConverter _converters["double"] = DoubleConverter _converters["const double&"] = ConstDoubleRefConverter +_converters["long double"] = LongDoubleConverter +_converters["const long double&"] = ConstLongDoubleRefConverter _converters["const char*"] = CStringConverter _converters["void*"] = VoidPtrConverter _converters["void**"] = VoidPtrPtrConverter @@ -837,7 +858,8 @@ def _add_aliased_converters(): "NOT_RPYTHON" aliases = ( - ("char", "unsigned char"), + ("char", "unsigned char"), # TODO: check + ("char", "signed char"), # TODO: check ("const char*", "char*"), ("std::basic_string<char>", "string"), diff --git a/pypy/module/cppyy/executor.py b/pypy/module/cppyy/executor.py --- a/pypy/module/cppyy/executor.py +++ b/pypy/module/cppyy/executor.py @@ -318,7 +318,8 @@ "NOT_RPYTHON" type_info = ( (bool, capi.c_call_b, ("bool",)), - (rffi.CHAR, capi.c_call_c, ("char", "unsigned char")), + # TODO: either signed or unsigned is correct for a given platform ... + (rffi.CHAR, capi.c_call_c, ("char", "unsigned char", "signed char")), (rffi.SHORT, capi.c_call_h, ("short", "short int", "unsigned short", "unsigned short int")), (rffi.INT, capi.c_call_i, ("int", "internal_enum_type_t")), (rffi.UINT, capi.c_call_l, ("unsigned", "unsigned int")), @@ -328,6 +329,7 @@ (rffi.ULONGLONG, capi.c_call_ll, ("unsigned long long", "unsigned long long int", "ULong64_t")), (rffi.FLOAT, capi.c_call_f, ("float",)), (rffi.DOUBLE, capi.c_call_d, ("double",)), + (rffi.LONGDOUBLE, capi.c_call_ld, ("long double",)), ) for c_type, stub, names in type_info: diff --git a/pypy/module/cppyy/ffitypes.py b/pypy/module/cppyy/ffitypes.py --- a/pypy/module/cppyy/ffitypes.py +++ b/pypy/module/cppyy/ffitypes.py @@ -241,11 +241,16 @@ c_type = rffi.LONGDOUBLE c_ptrtype = rffi.LONGDOUBLEP - typecode = 'D' + typecode = 'g' def _unwrap_object(self, space, w_obj): return space.float_w(w_obj) + def _wrap_object(self, space, obj): + # long double not really supported, so force a cast to double + dbl = rffi.cast(rffi.DOUBLE, obj) + return space.wrap(float(dbl)) + def cffi_type(self, space): state = space.fromcache(State) return state.c_ldouble diff --git a/pypy/module/cppyy/include/capi.h b/pypy/module/cppyy/include/capi.h --- a/pypy/module/cppyy/include/capi.h +++ b/pypy/module/cppyy/include/capi.h @@ -55,6 +55,8 @@ float cppyy_call_f(cppyy_method_t method, cppyy_object_t self, int nargs, void* args); RPY_EXTERN double cppyy_call_d(cppyy_method_t method, cppyy_object_t self, int nargs, void* args); + RPY_EXTERN + long double cppyy_call_ld(cppyy_method_t method, cppyy_object_t self, int nargs, void* args); RPY_EXTERN void* cppyy_call_r(cppyy_method_t method, cppyy_object_t self, int nargs, void* args); diff --git a/pypy/module/cppyy/src/clingcwrapper.cxx b/pypy/module/cppyy/src/clingcwrapper.cxx --- a/pypy/module/cppyy/src/clingcwrapper.cxx +++ b/pypy/module/cppyy/src/clingcwrapper.cxx @@ -1255,6 +1255,11 @@ return (double)Cppyy::CallD(method, (void*)self, &parvec); } +long double cppyy_call_ld(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) { + std::vector<TParameter> parvec = vsargs_to_parvec(args, nargs); + return (long double)Cppyy::CallLD(method, (void*)self, &parvec); +} + void* cppyy_call_r(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) { std::vector<TParameter> parvec = vsargs_to_parvec(args, nargs); return (void*)Cppyy::CallR(method, (void*)self, &parvec); diff --git a/pypy/module/cppyy/test/test_datatypes.py b/pypy/module/cppyy/test/test_datatypes.py --- a/pypy/module/cppyy/test/test_datatypes.py +++ b/pypy/module/cppyy/test/test_datatypes.py @@ -15,20 +15,20 @@ spaceconfig = dict(usemodules=['cppyy', '_rawffi', 'itertools']) def setup_class(cls): - cls.w_N = cls.space.wrap(5) # should be imported from the dictionary cls.w_test_dct = cls.space.wrap(test_dct) cls.w_datatypes = cls.space.appexec([], """(): import cppyy return cppyy.load_reflection_info(%r)""" % (test_dct, )) + cls.w_N = cls.space.wrap(5) # should be imported from the dictionary def test01_load_reflection_cache(self): - """Test whether loading a refl. info twice results in the same object.""" + """Loading reflection info twice should result in the same object""" import cppyy lib2 = cppyy.load_reflection_info(self.test_dct) assert self.datatypes is lib2 def test02_instance_data_read_access(self): - """Test read access to instance public data and verify values""" + """Read access to instance public data and verify values""" import cppyy CppyyTestData = cppyy.gbl.CppyyTestData @@ -38,62 +38,63 @@ # reading boolean type assert c.m_bool == False + assert not c.get_bool(); assert not c.get_bool_cr(); assert not c.get_bool_r() # reading char types assert c.m_char == 'a' + assert c.m_schar == 'b' assert c.m_uchar == 'c' # reading integer types - assert c.m_short == -11 - assert c.m_ushort == 11 - assert c.m_int == -22 - assert c.m_uint == 22 - assert c.m_long == -33 - assert c.m_ulong == 33 - assert c.m_llong == -44 - assert c.m_ullong == 44 + assert c.m_short == -11; assert c.get_short_cr() == -11; assert c.get_short_r() == -11 + assert c.m_ushort == 11; assert c.get_ushort_cr() == 11; assert c.get_ushort_r() == 11 + assert c.m_int == -22; assert c.get_int_cr() == -22; assert c.get_int_r() == -22 + assert c.m_uint == 22; assert c.get_uint_cr() == 22; assert c.get_uint_r() == 22 + assert c.m_long == -33; assert c.get_long_cr() == -33; assert c.get_long_r() == -33 + assert c.m_ulong == 33; assert c.get_ulong_cr() == 33; assert c.get_ulong_r() == 33 + assert c.m_llong == -44; assert c.get_llong_cr() == -44; assert c.get_llong_r() == -44 + assert c.m_ullong == 44; assert c.get_ullong_cr() == 44; assert c.get_ullong_r() == 44 + assert c.m_long64 == -55; assert c.get_long64_cr() == -55; assert c.get_long64_r() == -55 + assert c.m_ulong64 == 55; assert c.get_ulong64_cr() == 55; assert c.get_ulong64_r() == 55 # reading floating point types - assert round(c.m_float + 66., 5) == 0 + assert round(c.m_float + 66., 5) == 0 + assert round(c.get_float_cr() + 66., 5) == 0 + assert round(c.get_float_r() + 66., 5) == 0 + assert round(c.m_double + 77., 11) == 0 + assert round(c.get_double_cr() + 77., 11) == 0 + assert round(c.get_double_r() + 77., 11) == 0 + assert round(c.m_ldouble + 88., 24) == 0 + assert round(c.get_ldouble_cr() + 88., 24) == 0 + assert round(c.get_ldouble_r() + 88., 24) == 0 assert round(c.m_double + 77., 8) == 0 - # reding of array types + # reading of enum types + assert c.m_enum == CppyyTestData.kNothing + assert c.m_enum == c.kNothing + + # reading of boolean array for i in range(self.N): - # reading of integer array types assert c.m_bool_array[i] == bool(i%2) assert c.get_bool_array()[i] == bool(i%2) assert c.m_bool_array2[i] == bool((i+1)%2) assert c.get_bool_array2()[i] == bool((i+1)%2) - assert c.m_short_array[i] == -1*i - assert c.get_short_array()[i] == -1*i - assert c.m_short_array2[i] == -2*i - assert c.get_short_array2()[i] == -2*i - assert c.m_ushort_array[i] == 3*i - assert c.get_ushort_array()[i] == 3*i - assert c.m_ushort_array2[i] == 4*i - assert c.get_ushort_array2()[i] == 4*i - assert c.m_int_array[i] == -5*i - assert c.get_int_array()[i] == -5*i - assert c.m_int_array2[i] == -6*i - assert c.get_int_array2()[i] == -6*i - assert c.m_uint_array[i] == 7*i - assert c.get_uint_array()[i] == 7*i - assert c.m_uint_array2[i] == 8*i - assert c.get_uint_array2()[i] == 8*i - assert c.m_long_array[i] == -9*i - assert c.get_long_array()[i] == -9*i - assert c.m_long_array2[i] == -10*i - assert c.get_long_array2()[i] == -10*i - assert c.m_ulong_array[i] == 11*i - assert c.get_ulong_array()[i] == 11*i - assert c.m_ulong_array2[i] == 12*i - assert c.get_ulong_array2()[i] == 12*i + # reading of integer array types + names = [ 'short', 'ushort', 'int', 'uint', 'long', 'ulong'] + alpha = [(-1, -2), (3, 4), (-5, -6), (7, 8), (-9, -10), (11, 12)] + for j in range(self.N): + assert getattr(c, 'm_%s_array' % names[i])[i] == alpha[i][0]*i + assert getattr(c, 'get_%s_array' % names[i])()[i] == alpha[i][0]*i + assert getattr(c, 'm_%s_array2' % names[i])[i] == alpha[i][1]*i + assert getattr(c, 'get_%s_array2' % names[i])()[i] == alpha[i][1]*i - assert round(c.m_float_array[i] + 13.*i, 5) == 0 - assert round(c.m_float_array2[i] + 14.*i, 5) == 0 - assert round(c.m_double_array[i] + 15.*i, 8) == 0 - assert round(c.m_double_array2[i] + 16.*i, 8) == 0 + # reading of floating point array types + for k in range(self.N): + assert round(c.m_float_array[k] + 13.*k, 5) == 0 + assert round(c.m_float_array2[k] + 14.*k, 5) == 0 + assert round(c.m_double_array[k] + 15.*k, 8) == 0 + assert round(c.m_double_array2[k] + 16.*k, 8) == 0 # out-of-bounds checks raises(IndexError, c.m_short_array.__getitem__, self.N) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit