Author: Wim Lavrijsen <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit