[pypy-commit] pypy reflex-support: stricter handling of r_float and bool and associated tests
wlav
noreply at buildbot.pypy.org
Thu Jul 12 09:10:31 CEST 2012
Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r56037:f800d0b2a935
Date: 2012-07-11 22:42 -0700
http://bitbucket.org/pypy/pypy/changeset/f800d0b2a935/
Log: stricter handling of r_float and bool and associated tests
diff --git a/pypy/module/cppyy/capi/__init__.py b/pypy/module/cppyy/capi/__init__.py
--- a/pypy/module/cppyy/capi/__init__.py
+++ b/pypy/module/cppyy/capi/__init__.py
@@ -109,7 +109,7 @@
compilation_info=backend.eci)
c_call_b = rffi.llexternal(
"cppyy_call_b",
- [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.INT,
+ [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.UCHAR,
threadsafe=ts_call,
compilation_info=backend.eci)
c_call_c = rffi.llexternal(
@@ -139,7 +139,7 @@
compilation_info=backend.eci)
c_call_f = rffi.llexternal(
"cppyy_call_f",
- [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.DOUBLE,
+ [C_METHOD, C_OBJECT, rffi.INT, rffi.VOIDP], rffi.FLOAT,
threadsafe=ts_call,
compilation_info=backend.eci)
c_call_d = rffi.llexternal(
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
@@ -244,16 +244,8 @@
space.wrap('no converter available for type "%s"' % self.name))
-class BoolConverter(TypeConverter):
+class BoolConverter(ffitypes.typeid(bool), TypeConverter):
_immutable_ = True
- libffitype = libffi.types.schar
-
- def _unwrap_object(self, space, w_obj):
- arg = space.c_int_w(w_obj)
- if arg != False and arg != True:
- raise OperationError(space.w_ValueError,
- space.wrap("boolean value should be bool, or integer 1 or 0"))
- return arg
def convert_argument(self, space, w_obj, address, call_local):
x = rffi.cast(rffi.LONGP, address)
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
@@ -72,16 +72,16 @@
_mixin_ = True
_immutable_ = True
- def _wrap_result(self, space, result):
- return space.wrap(rffi.cast(self.c_type, result))
+ def _wrap_object(self, space, obj):
+ return space.wrap(obj)
def execute(self, space, cppmethod, cppthis, num_args, args):
result = self.c_stubcall(cppmethod, cppthis, num_args, args)
- return self._wrap_result(space, result)
+ return self._wrap_object(space, rffi.cast(self.c_type, result))
def execute_libffi(self, space, libffifunc, argchain):
result = libffifunc.call(argchain, self.c_type)
- return space.wrap(result)
+ return self._wrap_object(space, result)
class NumericRefExecutorMixin(object):
_mixin_ = True
@@ -96,71 +96,22 @@
self.item = self._unwrap_object(space, w_item)
self.do_assign = True
- def _wrap_result(self, space, rffiptr):
+ def _wrap_object(self, space, obj):
+ return space.wrap(rffi.cast(self.c_type, obj))
+
+ def _wrap_reference(self, space, rffiptr):
if self.do_assign:
rffiptr[0] = self.item
- return space.wrap(rffiptr[0]) # all paths, for rtyper
+ self.do_assign = False
+ return self._wrap_object(space, rffiptr[0]) # all paths, for rtyper
def execute(self, space, cppmethod, cppthis, num_args, args):
- result = rffi.cast(self.c_ptrtype, capi.c_call_r(cppmethod, cppthis, num_args, args))
- return self._wrap_result(space, result)
+ result = capi.c_call_r(cppmethod, cppthis, num_args, args)
+ return self._wrap_reference(space, rffi.cast(self.c_ptrtype, result))
def execute_libffi(self, space, libffifunc, argchain):
result = libffifunc.call(argchain, self.c_ptrtype)
- return self._wrap_result(space, result)
-
-
-class BoolExecutor(FunctionExecutor):
- _immutable_ = True
- libffitype = libffi.types.schar
-
- def execute(self, space, cppmethod, cppthis, num_args, args):
- result = capi.c_call_b(cppmethod, cppthis, num_args, args)
- return space.wrap(result)
-
- def execute_libffi(self, space, libffifunc, argchain):
- result = libffifunc.call(argchain, rffi.CHAR)
- return space.wrap(bool(ord(result)))
-
-class ConstIntRefExecutor(FunctionExecutor):
- _immutable_ = True
- libffitype = libffi.types.pointer
-
- def _wrap_result(self, space, result):
- intptr = rffi.cast(rffi.INTP, result)
- return space.wrap(intptr[0])
-
- def execute(self, space, cppmethod, cppthis, num_args, args):
- result = capi.c_call_r(cppmethod, cppthis, num_args, args)
- return self._wrap_result(space, result)
-
- def execute_libffi(self, space, libffifunc, argchain):
- result = libffifunc.call(argchain, rffi.INTP)
- return space.wrap(result[0])
-
-class ConstLongRefExecutor(ConstIntRefExecutor):
- _immutable_ = True
- libffitype = libffi.types.pointer
-
- def _wrap_result(self, space, result):
- longptr = rffi.cast(rffi.LONGP, result)
- return space.wrap(longptr[0])
-
- def execute_libffi(self, space, libffifunc, argchain):
- result = libffifunc.call(argchain, rffi.LONGP)
- return space.wrap(result[0])
-
-class FloatExecutor(FunctionExecutor):
- _immutable_ = True
- libffitype = libffi.types.float
-
- def execute(self, space, cppmethod, cppthis, num_args, args):
- result = capi.c_call_f(cppmethod, cppthis, num_args, args)
- return space.wrap(float(result))
-
- def execute_libffi(self, space, libffifunc, argchain):
- result = libffifunc.call(argchain, rffi.FLOAT)
- return space.wrap(float(result))
+ return self._wrap_reference(space, result)
class CStringExecutor(FunctionExecutor):
@@ -329,14 +280,11 @@
_executors["void"] = VoidExecutor
_executors["void*"] = PtrTypeExecutor
-_executors["bool"] = BoolExecutor
_executors["const char*"] = CStringExecutor
-_executors["const int&"] = ConstIntRefExecutor
-_executors["float"] = FloatExecutor
+# special cases
_executors["constructor"] = ConstructorExecutor
-# special cases
_executors["std::basic_string<char>"] = StdStringExecutor
_executors["const std::basic_string<char>&"] = StdStringExecutor
_executors["std::basic_string<char>&"] = StdStringExecutor # TODO: shouldn't copy
@@ -347,6 +295,7 @@
def _build_basic_executors():
"NOT_RPYTHON"
type_info = (
+ (bool, capi.c_call_b, ("bool",)),
(rffi.CHAR, capi.c_call_c, ("char", "unsigned char")),
(rffi.SHORT, capi.c_call_h, ("short", "short int", "unsigned short", "unsigned short int")),
(rffi.INT, capi.c_call_i, ("int",)),
@@ -355,7 +304,8 @@
(rffi.ULONG, capi.c_call_l, ("unsigned long", "unsigned long int")),
(rffi.LONGLONG, capi.c_call_ll, ("long long", "long long int")),
(rffi.ULONGLONG, capi.c_call_ll, ("unsigned long long", "unsigned long long int")),
- (rffi.DOUBLE, capi.c_call_d, ("double",))
+ (rffi.FLOAT, capi.c_call_f, ("float",)),
+ (rffi.DOUBLE, capi.c_call_d, ("double",)),
)
for c_type, stub, names in type_info:
@@ -366,8 +316,9 @@
_immutable_ = True
libffitype = libffi.types.pointer
for name in names:
- _executors[name] = BasicExecutor
- _executors[name+'&'] = BasicRefExecutor
+ _executors[name] = BasicExecutor
+ _executors[name+'&'] = BasicRefExecutor
+ _executors['const '+name+'&'] = BasicRefExecutor # no copy needed for builtins
_build_basic_executors()
# create the pointer executors; all real work is in the PtrTypeExecutor, since
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
@@ -10,6 +10,23 @@
# mixin, a non-RPython function typeid() is used.
+class BoolTypeMixin(object):
+ _mixin_ = True
+ _immutable_ = True
+ libffitype = libffi.types.uchar
+ c_type = rffi.UCHAR
+ c_ptrtype = rffi.UCHARP
+
+ def _unwrap_object(self, space, w_obj):
+ arg = space.c_int_w(w_obj)
+ if arg != False and arg != True:
+ raise OperationError(space.w_ValueError,
+ space.wrap("boolean value should be bool, or integer 1 or 0"))
+ return arg
+
+ def _wrap_object(self, space, obj):
+ return space.wrap(bool(ord(rffi.cast(rffi.CHAR, obj))))
+
class CharTypeMixin(object):
_mixin_ = True
_immutable_ = True
@@ -125,6 +142,9 @@
def _unwrap_object(self, space, w_obj):
return r_singlefloat(space.float_w(w_obj))
+ def _wrap_object(self, space, obj):
+ return space.wrap(float(obj))
+
class DoubleTypeMixin(object):
_mixin_ = True
_immutable_ = True
@@ -139,6 +159,7 @@
def typeid(c_type):
"NOT_RPYTHON"
+ if c_type == bool: return BoolTypeMixin
if c_type == rffi.CHAR: return CharTypeMixin
if c_type == rffi.SHORT: return ShortTypeMixin
if c_type == rffi.USHORT: return UShortTypeMixin
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
@@ -30,13 +30,13 @@
/* method/function dispatching -------------------------------------------- */
void cppyy_call_v(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
- int cppyy_call_b(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
+ unsigned char cppyy_call_b(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
char cppyy_call_c(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
short cppyy_call_h(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
int cppyy_call_i(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
long cppyy_call_l(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
long long cppyy_call_ll(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
- double cppyy_call_f(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
+ float cppyy_call_f(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
double cppyy_call_d(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
void* cppyy_call_r(cppyy_method_t method, cppyy_object_t self, int nargs, void* args);
diff --git a/pypy/module/cppyy/src/cintcwrapper.cxx b/pypy/module/cppyy/src/cintcwrapper.cxx
--- a/pypy/module/cppyy/src/cintcwrapper.cxx
+++ b/pypy/module/cppyy/src/cintcwrapper.cxx
@@ -384,9 +384,9 @@
cppyy_call_T(method, self, nargs, args);
}
-int cppyy_call_b(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
+unsigned char cppyy_call_b(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
G__value result = cppyy_call_T(method, self, nargs, args);
- return (bool)G__int(result);
+ return (unsigned char)(bool)G__int(result);
}
char cppyy_call_c(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
@@ -414,9 +414,9 @@
return G__Longlong(result);
}
-double cppyy_call_f(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
+float cppyy_call_f(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
G__value result = cppyy_call_T(method, self, nargs, args);
- return G__double(result);
+ return (float)G__double(result);
}
double cppyy_call_d(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
diff --git a/pypy/module/cppyy/src/reflexcwrapper.cxx b/pypy/module/cppyy/src/reflexcwrapper.cxx
--- a/pypy/module/cppyy/src/reflexcwrapper.cxx
+++ b/pypy/module/cppyy/src/reflexcwrapper.cxx
@@ -133,8 +133,8 @@
return result;
}
-int cppyy_call_b(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
- return (int)cppyy_call_T<bool>(method, self, nargs, args);
+unsigned char cppyy_call_b(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
+ return (unsigned char)cppyy_call_T<bool>(method, self, nargs, args);
}
char cppyy_call_c(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
@@ -157,7 +157,7 @@
return cppyy_call_T<long long>(method, self, nargs, args);
}
-double cppyy_call_f(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
+float cppyy_call_f(cppyy_method_t method, cppyy_object_t self, int nargs, void* args) {
return cppyy_call_T<float>(method, self, nargs, args);
}
diff --git a/pypy/module/cppyy/test/stltypes.cxx b/pypy/module/cppyy/test/stltypes.cxx
--- a/pypy/module/cppyy/test/stltypes.cxx
+++ b/pypy/module/cppyy/test/stltypes.cxx
@@ -14,6 +14,7 @@
//- explicit instantiations of used types
STLTYPES_EXPLICIT_INSTANTIATION(vector, int)
+STLTYPES_EXPLICIT_INSTANTIATION(vector, float)
STLTYPES_EXPLICIT_INSTANTIATION(vector, double)
STLTYPES_EXPLICIT_INSTANTIATION(vector, just_a_class)
diff --git a/pypy/module/cppyy/test/stltypes.h b/pypy/module/cppyy/test/stltypes.h
--- a/pypy/module/cppyy/test/stltypes.h
+++ b/pypy/module/cppyy/test/stltypes.h
@@ -25,6 +25,7 @@
#ifndef __CINT__
//- explicit instantiations of used types
STLTYPES_EXPLICIT_INSTANTIATION_DECL(vector, int)
+STLTYPES_EXPLICIT_INSTANTIATION_DECL(vector, float)
STLTYPES_EXPLICIT_INSTANTIATION_DECL(vector, double)
STLTYPES_EXPLICIT_INSTANTIATION_DECL(vector, just_a_class)
#endif
diff --git a/pypy/module/cppyy/test/test_cint.py b/pypy/module/cppyy/test/test_cint.py
--- a/pypy/module/cppyy/test/test_cint.py
+++ b/pypy/module/cppyy/test/test_cint.py
@@ -87,3 +87,26 @@
c.set_data(13)
assert c.m_data == 13
assert c.get_data() == 13
+
+
+class AppTestCINTPythonizations:
+ def setup_class(cls):
+ cls.space = space
+
+ def test03_TVector(self):
+ """Test TVector2/3/T behavior"""
+
+ import cppyy, math
+
+ N = 51
+
+ # TVectorF is a typedef of floats
+ v = cppyy.gbl.TVectorF(N)
+ for i in range(N):
+ v[i] = i*i
+
+ #for j in v: # TODO: raise exception on out-of-bounds
+ # assert round(v[int(math.sqrt(j)+0.5)]-j, 5) == 0.
+ for i in range(N):
+ j = v[i]
+ assert round(v[int(math.sqrt(j)+0.5)]-j, 5) == 0.
diff --git a/pypy/module/cppyy/test/test_stltypes.py b/pypy/module/cppyy/test/test_stltypes.py
--- a/pypy/module/cppyy/test/test_stltypes.py
+++ b/pypy/module/cppyy/test/test_stltypes.py
@@ -34,30 +34,27 @@
assert callable(cppyy.gbl.std.vector)
- tv1i = getattr(cppyy.gbl.std, 'vector<int>')
- tv2i = cppyy.gbl.std.vector(int)
- assert tv1i is tv2i
- assert cppyy.gbl.std.vector(int).iterator is cppyy.gbl.std.vector('int').iterator
+ type_info = (
+ ("int", int),
+ ("float", "float"),
+ ("double", "double"),
+ )
- tv1d = getattr(cppyy.gbl.std, 'vector<double>')
- tv2d = cppyy.gbl.std.vector('double')
- assert tv1d is tv2d
- assert tv1d.iterator is cppyy.gbl.std.vector('double').iterator
+ for c_type, p_type in type_info:
+ tv1 = getattr(cppyy.gbl.std, 'vector<%s>' % c_type)
+ tv2 = cppyy.gbl.std.vector(p_type)
+ assert tv1 is tv2
+ assert tv1.iterator is cppyy.gbl.std.vector(p_type).iterator
- #-----
- vi = tv1i(self.N)
- vd = tv1d(); vd += range(self.N) # default args from Reflex are useless :/
- def test_v(v):
+ #-----
+ v = tv1(); v += range(self.N) # default args from Reflex are useless :/
assert v.begin().__eq__(v.begin())
assert v.begin() == v.begin()
assert v.end() == v.end()
assert v.begin() != v.end()
assert v.end() != v.begin()
- test_v(vi)
- test_v(vd)
- #-----
- def test_v(v):
+ #-----
for i in range(self.N):
v[i] = i
assert v[i] == i
@@ -65,13 +62,9 @@
assert v.size() == self.N
assert len(v) == self.N
- test_v(vi)
- test_v(vd)
- #-----
- vi = tv1i()
- vd = tv1d()
- def test_v(v):
+ #-----
+ v = tv1()
for i in range(self.N):
v.push_back(i)
assert v.size() == i+1
@@ -80,8 +73,6 @@
assert v.size() == self.N
assert len(v) == self.N
- test_v(vi)
- test_v(vd)
def test02_user_type_vector_type(self):
"""Test access to an std::vector<just_a_class>"""
More information about the pypy-commit
mailing list