[pypy-commit] pypy reflex-support: merge heads
cfbolz
noreply at buildbot.pypy.org
Wed Jul 13 14:12:52 CEST 2011
Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: reflex-support
Changeset: r45538:6ff6f4beb1bf
Date: 2011-07-13 14:07 +0200
http://bitbucket.org/pypy/pypy/changeset/6ff6f4beb1bf/
Log: merge heads
diff --git a/pypy/module/cppyy/capi/cint_capi.py b/pypy/module/cppyy/capi/cint_capi.py
--- a/pypy/module/cppyy/capi/cint_capi.py
+++ b/pypy/module/cppyy/capi/cint_capi.py
@@ -107,6 +107,10 @@
"cppyy_call_h",
[C_TYPEHANDLE, rffi.INT, C_OBJECT, rffi.INT, rffi.VOIDPP], rffi.SHORT,
compilation_info=eci)
+c_call_i = rffi.llexternal(
+ "cppyy_call_i",
+ [C_TYPEHANDLE, rffi.INT, C_OBJECT, rffi.INT, rffi.VOIDPP], rffi.INT,
+ compilation_info=eci)
c_call_l = rffi.llexternal(
"cppyy_call_l",
[C_TYPEHANDLE, rffi.INT, C_OBJECT, rffi.INT, rffi.VOIDPP], rffi.LONG,
diff --git a/pypy/module/cppyy/capi/reflex_capi.py b/pypy/module/cppyy/capi/reflex_capi.py
--- a/pypy/module/cppyy/capi/reflex_capi.py
+++ b/pypy/module/cppyy/capi/reflex_capi.py
@@ -108,7 +108,7 @@
[C_TYPEHANDLE, rffi.INT, C_OBJECT, rffi.INT, rffi.VOIDPP], rffi.SHORT,
compilation_info=eci)
c_call_i = rffi.llexternal(
- "cppyy_call_l",
+ "cppyy_call_i",
[C_TYPEHANDLE, rffi.INT, C_OBJECT, rffi.INT, rffi.VOIDPP], rffi.INT,
compilation_info=eci)
c_call_l = 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
@@ -288,7 +288,7 @@
libffitype = libffi.types.ulong
def _unwrap_object(self, space, w_obj):
- return space.c_uint_w(w_obj)
+ return space.uint_w(w_obj)
def convert_argument(self, space, w_obj):
arg = self._unwrap_object(space, w_obj)
@@ -376,6 +376,11 @@
x = rffi.str2charp(arg)
return rffi.cast(rffi.VOIDP, x)
+ def from_memory(self, space, w_obj, offset):
+ address = self._get_raw_address(space, w_obj, offset)
+ charpptr = rffi.cast(rffi.CCHARPP, address)
+ return space.wrap(rffi.charp2str(charpptr[0]))
+
class ShortArrayConverter(ArrayTypeConverterMixin, TypeConverter):
_immutable_=True
@@ -566,3 +571,4 @@
_converters["double*"] = DoublePtrConverter
_converters["double[]"] = DoubleArrayConverter
_converters["const char*"] = CStringConverter
+_converters["char*"] = CStringConverter
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
@@ -92,10 +92,10 @@
libffitype = libffi.types.uint
def _wrap_result(self, space, result):
- return space.wrap(result)
+ return space.wrap(rffi.cast(rffi.UINT, result))
def execute(self, space, func, cppthis, num_args, args):
- result = capi.c_call_i(func.cpptype.handle, func.method_index, cppthis, num_args, args)
+ result = capi.c_call_l(func.cpptype.handle, func.method_index, cppthis, num_args, args)
return self._wrap_result(space, result)
class LongExecutor(FunctionExecutor):
@@ -112,6 +112,13 @@
def execute_libffi(self, space, libffifunc, argchain):
return space.wrap(libffifunc.call(argchain, lltype.Signed))
+class UnsignedLongExecutor(LongExecutor):
+ _immutable_ = True
+ libffitype = libffi.types.ulong
+
+ def _wrap_result(self, space, result):
+ return space.wrap(rffi.cast(rffi.ULONG, result))
+
class ConstIntRefExecutor(LongExecutor):
_immutable_ = True
@@ -170,6 +177,10 @@
_immutable_ = True
typecode = 'l'
+class UnsignedLongPtrExecutor(PtrTypeExecutor):
+ _immutable_ = True
+ typecode = 'L'
+
class FloatPtrExecutor(PtrTypeExecutor):
_immutable_ = True
typecode = 'f'
@@ -189,7 +200,7 @@
from pypy.module.cppyy import interp_cppyy
long_result = capi.c_call_l(func.cpptype.handle, func.method_index, cppthis, num_args, args)
ptr_result = rffi.cast(rffi.VOIDP, long_result)
- return interp_cppyy.W_CPPInstance(space, self.cpptype, ptr_result)
+ return interp_cppyy.W_CPPInstance(space, self.cpptype, ptr_result, False)
class InstanceExecutor(InstancePtrExecutor):
_immutable_ = True
@@ -199,8 +210,7 @@
long_result = capi.c_call_o(
func.cpptype.handle, func.method_index, cppthis, num_args, args, self.cpptype.handle)
ptr_result = rffi.cast(rffi.VOIDP, long_result)
- # TODO: take ownership of result ...
- return interp_cppyy.W_CPPInstance(space, self.cpptype, ptr_result)
+ return interp_cppyy.W_CPPInstance(space, self.cpptype, ptr_result, True)
_executors = {}
@@ -275,8 +285,8 @@
_executors["unsigned int*"] = UnsignedIntPtrExecutor
_executors["long int"] = LongExecutor
_executors["long int*"] = LongPtrExecutor
-_executors["unsigned long int"] = LongExecutor
-_executors["unsigned long int*"] = LongPtrExecutor
+_executors["unsigned long int"] = UnsignedLongExecutor
+_executors["unsigned long int*"] = UnsignedLongPtrExecutor
_executors["float"] = FloatExecutor
_executors["float*"] = FloatPtrExecutor
_executors["double"] = DoubleExecutor
diff --git a/pypy/module/cppyy/interp_cppyy.py b/pypy/module/cppyy/interp_cppyy.py
--- a/pypy/module/cppyy/interp_cppyy.py
+++ b/pypy/module/cppyy/interp_cppyy.py
@@ -227,7 +227,7 @@
except Exception, e:
capi.c_deallocate(self.cpptype.handle, newthis)
raise
- return W_CPPInstance(self.space, self.cpptype, newthis)
+ return W_CPPInstance(self.space, self.cpptype, newthis, True)
class W_CPPOverload(Wrappable):
@@ -246,13 +246,22 @@
return self.space.wrap(self.functions[0].executor.name)
@jit.unroll_safe
- def call(self, cppthis, args_w):
+ def call(self, cppinstance, args_w):
+ if cppinstance:
+ cppthis = cppinstance.rawobject
+ else:
+ cppthis = NULL_VOIDP
+
space = self.space
errmsg = 'None of the overloads matched:'
for i in range(len(self.functions)):
cppyyfunc = self.functions[i]
try:
- return cppyyfunc.call(cppthis, args_w)
+ cppresult = cppyyfunc.call(cppthis, args_w)
+ if cppinstance and isinstance(cppresult, W_CPPInstance):
+ if cppresult.rawobject == cppinstance.rawobject:
+ return cppinstance # recycle object to preserve identity
+ return cppresult
except OperationError, e:
if not e.match(space, space.w_TypeError):
raise
@@ -377,7 +386,7 @@
self.space.wrap(str("class %s has no attribute %s" % (self.name, name))))
def invoke(self, overload, args_w):
- return overload.call(NULL_VOIDP, args_w)
+ return overload.call(None, args_w)
W_CPPScope.typedef = TypeDef(
'CPPScope',
@@ -484,7 +493,7 @@
self.space.wrap("%s is abstract" % self.name))
raise
- return overload.call(NULL_VOIDP, args_w)
+ return overload.call(None, args_w)
W_CPPType.typedef = TypeDef(
'CPPType',
@@ -521,10 +530,11 @@
class W_CPPInstance(Wrappable):
_immutable_fields_ = ["cppclass"]
- def __init__(self, space, cppclass, rawobject):
+ def __init__(self, space, cppclass, rawobject, python_owns):
self.space = space
self.cppclass = cppclass
self.rawobject = rawobject
+ self.python_owns = python_owns
def _nullcheck(self):
if not self.rawobject:
@@ -532,11 +542,16 @@
def invoke(self, overload, args_w):
self._nullcheck()
- return overload.call(self.rawobject, args_w)
+ return overload.call(self, args_w)
def destruct(self):
- capi.c_destruct(self.cppclass.handle, self.rawobject)
- self.rawobject = NULL_VOIDP
+ if self.rawobject:
+ capi.c_destruct(self.cppclass.handle, self.rawobject)
+ self.rawobject = NULL_VOIDP
+
+ def __del__(self):
+ if self.python_owns:
+ self.destruct()
W_CPPInstance.typedef = TypeDef(
'CPPInstance',
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
@@ -128,6 +128,12 @@
return (short)G__int(result);
}
+int cppyy_call_i(cppyy_typehandle_t handle, int method_index,
+ cppyy_object_t self, int numargs, void* args[]) {
+ G__value result = cppyy_call_T(handle, method_index, self, numargs, args);
+ return (int)G__int(result);
+}
+
long cppyy_call_l(cppyy_typehandle_t handle, int method_index,
cppyy_object_t self, int numargs, void* args[]) {
G__value result = cppyy_call_T(handle, method_index, self, numargs, args);
diff --git a/pypy/module/cppyy/test/example01.cxx b/pypy/module/cppyy/test/example01.cxx
--- a/pypy/module/cppyy/test/example01.cxx
+++ b/pypy/module/cppyy/test/example01.cxx
@@ -7,12 +7,28 @@
#include "example01.h"
//===========================================================================
-payload::payload(double d) : m_data(d) {}
-payload::payload(const payload& p) : m_data(p.m_data) {}
+payload::payload(double d) : m_data(d) {
+ count++;
+}
+payload::payload(const payload& p) : m_data(p.m_data) {
+ count++;
+}
+payload& payload::operator=(const payload& p) {
+ if (this != &p) {
+ m_data = p.m_data;
+ }
+ return *this;
+}
+payload::~payload() {
+ count--;
+}
double payload::getData() { return m_data; }
void payload::setData(double d) { m_data = d; }
+// class-level data
+int payload::count = 0;
+
//===========================================================================
example01::example01() : m_somedata(-99) {
diff --git a/pypy/module/cppyy/test/example01.h b/pypy/module/cppyy/test/example01.h
--- a/pypy/module/cppyy/test/example01.h
+++ b/pypy/module/cppyy/test/example01.h
@@ -2,10 +2,15 @@
public:
payload(double d);
payload(const payload& p);
+ payload& operator=(const payload& e);
+ ~payload();
double getData();
void setData(double d);
+public: // class-level data
+ static int count;
+
private:
double m_data;
};
diff --git a/pypy/module/cppyy/test/operators.cxx b/pypy/module/cppyy/test/operators.cxx
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/test/operators.cxx
@@ -0,0 +1,1 @@
+#include "operators.h"
diff --git a/pypy/module/cppyy/test/operators.h b/pypy/module/cppyy/test/operators.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cppyy/test/operators.h
@@ -0,0 +1,97 @@
+class number {
+public:
+ number() { m_int = 0; }
+ number(int i) { m_int = i; }
+
+ int AsInt() { return m_int; }
+
+ number operator+(const number& n) const { return number(m_int + n.m_int); }
+ number operator+(int n) const { return number(m_int + n); }
+ number operator-(const number& n) const { return number(m_int - n.m_int); }
+ number operator-(int n) const { return number(m_int - n); }
+ number operator*(const number& n) const { return number(m_int * n.m_int); }
+ number operator*(int n) const { return number(m_int * n); }
+ number operator/(const number& n) const { return number(m_int / n.m_int); }
+ number operator/(int n) const { return number(m_int / n); }
+ number operator%(const number& n) const { return number(m_int % n.m_int); }
+ number operator%(int n) const { return number(m_int % n); }
+
+ number& operator+=(const number& n) { m_int += n.m_int; return *this; }
+ number& operator-=(const number& n) { m_int -= n.m_int; return *this; }
+ number& operator*=(const number& n) { m_int *= n.m_int; return *this; }
+ number& operator/=(const number& n) { m_int /= n.m_int; return *this; }
+ number& operator%=(const number& n) { m_int %= n.m_int; return *this; }
+
+ number operator-() { return number( -m_int ); }
+
+ bool operator<(const number& n) const { return m_int < n.m_int; }
+ bool operator>(const number& n) const { return m_int > n.m_int; }
+ bool operator<=(const number& n) const { return m_int <= n.m_int; }
+ bool operator>=(const number& n) const { return m_int >= n.m_int; }
+ bool operator!=(const number& n) const { return m_int != n.m_int; }
+ bool operator==(const number& n) const { return m_int == n.m_int; }
+
+ operator bool() { return m_int != 0; }
+
+ number operator&(const number& n) const { return number(m_int & n.m_int); }
+ number operator|(const number& n) const { return number(m_int | n.m_int); }
+ number operator^(const number& n) const { return number(m_int ^ n.m_int); }
+
+ number& operator&=(const number& n) { m_int &= n.m_int; return *this; }
+ number& operator|=(const number& n) { m_int |= n.m_int; return *this; }
+ number& operator^=(const number& n) { m_int ^= n.m_int; return *this; }
+
+ number operator<<(int i) const { return number(m_int << i); }
+ number operator>>(int i) const { return number(m_int >> i); }
+
+private:
+ int m_int;
+};
+
+//----------------------------------------------------------------------------
+struct operator_char_star { // for testing user-defined implicit casts
+ operator_char_star() : m_str((char*)"operator_char_star") {}
+ operator char*() { return m_str; }
+ char* m_str;
+};
+
+struct operator_const_char_star {
+ operator_const_char_star() : m_str("operator_const_char_star" ) {}
+ operator const char*() { return m_str; }
+ const char* m_str;
+};
+
+struct operator_int {
+ operator int() { return m_int; }
+ int m_int;
+};
+
+struct operator_long {
+ operator long() { return m_long; }
+ long m_long;
+};
+
+struct operator_double {
+ operator double() { return m_double; }
+ double m_double;
+};
+
+struct operator_short {
+ operator short() { return m_short; }
+ unsigned short m_short;
+};
+
+struct operator_unsigned_int {
+ operator unsigned int() { return m_uint; }
+ unsigned int m_uint;
+};
+
+struct operator_unsigned_long {
+ operator unsigned long() { return m_ulong; }
+ unsigned long m_ulong;
+};
+
+struct operator_float {
+ operator float() { return m_float; }
+ float m_float;
+};
diff --git a/pypy/module/cppyy/test/test_cppyy.py b/pypy/module/cppyy/test/test_cppyy.py
--- a/pypy/module/cppyy/test/test_cppyy.py
+++ b/pypy/module/cppyy/test/test_cppyy.py
@@ -111,6 +111,40 @@
e2.destruct()
assert t.invoke(t.get_overload("getCount")) == 0
+ e2.destruct()
+ assert t.invoke(t.get_overload("getCount")) == 0
+
+ def test_example01memory(self):
+ """Test memory destruction and integrity."""
+
+ import gc
+
+ t = self.example01
+
+ assert t.invoke(t.get_overload("getCount")) == 0
+
+ e1 = t.construct(7)
+ assert t.invoke(t.get_overload("getCount")) == 1
+ res = e1.invoke(t.get_overload("addDataToInt"), 4)
+ assert res == 11
+ res = e1.invoke(t.get_overload("addDataToInt"), -4)
+ assert res == 3
+ e1 = None
+ gc.collect()
+ assert t.invoke(t.get_overload("getCount")) == 0
+
+ e1 = t.construct(7)
+ e2 = t.construct(8)
+ assert t.invoke(t.get_overload("getCount")) == 2
+ e1 = None
+ gc.collect()
+ assert t.invoke(t.get_overload("getCount")) == 1
+ e2.destruct()
+ assert t.invoke(t.get_overload("getCount")) == 0
+ e2 = None
+ gc.collect()
+ assert t.invoke(t.get_overload("getCount")) == 0
+
def test_example01method_double(self):
"""Test passing of a double and returning of double on a method"""
diff --git a/pypy/module/cppyy/test/test_operators.py b/pypy/module/cppyy/test/test_operators.py
new file mode 100755
--- /dev/null
+++ b/pypy/module/cppyy/test/test_operators.py
@@ -0,0 +1,141 @@
+import py, os, sys
+from pypy.conftest import gettestobjspace
+
+
+currpath = py.path.local(__file__).dirpath()
+shared_lib = str(currpath.join("operatorsDict.so"))
+
+space = gettestobjspace(usemodules=['cppyy'])
+
+def setup_module(mod):
+ if sys.platform == 'win32':
+ py.test.skip("win32 not supported so far")
+ err = os.system("cd '%s' && make operatorsDict.so" % currpath)
+ if err:
+ raise OSError("'make' failed (see stderr)")
+
+class AppTestOPERATORS:
+ def setup_class(cls):
+ cls.space = space
+ env = os.environ
+ cls.w_N = space.wrap(5) # should be imported from the dictionary
+ cls.w_shared_lib = space.wrap(shared_lib)
+ cls.w_datatypes = cls.space.appexec([], """():
+ import cppyy
+ return cppyy.load_lib(%r)""" % (shared_lib, ))
+
+ def teardown_method(self, meth):
+ import gc
+ gc.collect()
+
+ def test01_math_operators(self):
+ """Test overloading of math operators"""
+
+ import cppyy
+ number = cppyy.gbl.number
+
+ assert (number(20) + number(10)) == number(30)
+ assert (number(20) + 10 ) == number(30)
+ assert (number(20) - number(10)) == number(10)
+ assert (number(20) - 10 ) == number(10)
+ assert (number(20) / number(10)) == number(2)
+ assert (number(20) / 10 ) == number(2)
+ assert (number(20) * number(10)) == number(200)
+ assert (number(20) * 10 ) == number(200)
+ assert (number(20) % 10 ) == number(0)
+ assert (number(20) % number(10)) == number(0)
+ assert (number(5) & number(14)) == number(4)
+ assert (number(5) | number(14)) == number(15)
+ assert (number(5) ^ number(14)) == number(11)
+ assert (number(5) << 2) == number(20)
+ assert (number(20) >> 2) == number(5)
+
+ def test02_unary_math_operators(self):
+ """Test overloading of unary math operators"""
+
+ import cppyy
+ number = cppyy.gbl.number
+
+ n = number(20)
+ n += number(10)
+ n -= number(10)
+ n *= number(10)
+ n /= number(2)
+ assert n == number(100)
+
+ nn = -n;
+ assert nn == number(-100)
+
+ def test03_comparison_operators(self):
+ """Test overloading of comparison operators"""
+
+ import cppyy
+ number = cppyy.gbl.number
+
+ assert (number(20) > number(10)) == True
+ assert (number(20) < number(10)) == False
+ assert (number(20) >= number(20)) == True
+ assert (number(20) <= number(10)) == False
+ assert (number(20) != number(10)) == True
+ assert (number(20) == number(10)) == False
+
+ def test04_boolean_operator(self):
+ """Test implementation of operator bool"""
+
+ import cppyy
+ number = cppyy.gbl.number
+
+ n = number(20)
+ assert n
+
+ n = number(0)
+ assert not n
+
+ def test05_exact_types(self):
+ """Test converter operators of exact types"""
+
+ import cppyy
+ gbl = cppyy.gbl
+
+ o = gbl.operator_char_star()
+ assert o.m_str == 'operator_char_star'
+ assert str(o) == 'operator_char_star'
+
+ o = gbl.operator_const_char_star()
+ assert o.m_str == 'operator_const_char_star'
+ assert str(o) == 'operator_const_char_star'
+
+ o = gbl.operator_int(); o.m_int = -13
+ assert o.m_int == -13
+ assert int(o) == -13
+
+ o = gbl.operator_long(); o.m_long = 42
+ assert o.m_long == 42
+ assert long(o) == 42
+
+ o = gbl.operator_double(); o.m_double = 3.1415
+ assert o.m_double == 3.1415
+ assert float(o) == 3.1415
+
+ def test06_approximate_types(self):
+ """Test converter operators of approximate types"""
+
+ import cppyy, sys
+ gbl = cppyy.gbl
+
+ o = gbl.operator_short(); o.m_short = 256
+ assert o.m_short == 256
+ assert int(o) == 256
+
+ o = gbl.operator_unsigned_int(); o.m_uint = 2147483647 + 32
+ assert o.m_uint == 2147483647 + 32
+ assert long(o) == 2147483647 + 32
+
+ o = gbl.operator_unsigned_long();
+ o.m_ulong = sys.maxint + 128
+ assert o.m_ulong == sys.maxint + 128
+ assert long(o) == sys.maxint + 128
+
+ o = gbl.operator_float(); o.m_float = 3.14
+ assert round(o.m_float - 3.14, 5) == 0.
+ assert round(float(o) - 3.14, 5) == 0.
diff --git a/pypy/module/cppyy/test/test_pythonify.py b/pypy/module/cppyy/test/test_pythonify.py
--- a/pypy/module/cppyy/test/test_pythonify.py
+++ b/pypy/module/cppyy/test/test_pythonify.py
@@ -199,3 +199,44 @@
assert cppyy.gbl.ns_example01.globalAddOneToInt(4) == 5
assert cppyy.gbl.ns_example01.globalAddOneToInt(4) == 5
+
+ def test09_memory(self):
+ import cppyy, gc
+ example01_class = cppyy.gbl.example01
+ payload_class = cppyy.gbl.payload
+
+ pl = payload_class(3.14)
+ assert payload_class.count == 1
+ assert round(pl.getData()-3.14, 8) == 0
+
+ pl2 = example01_class.staticCopyCyclePayload(pl, 38.)
+ assert payload_class.count == 2
+ assert pl2.getData() == 38.
+ pl2 = None
+ gc.collect()
+ assert payload_class.count == 1
+
+ e = example01_class(14)
+
+ pl2 = e.copyCyclePayload(pl)
+ assert payload_class.count == 2
+ assert round(pl2.getData()-14., 8) == 0
+ pl2 = None
+ gc.collect()
+ assert payload_class.count == 1
+
+ pl = None
+ e = None
+ gc.collect()
+ assert payload_class.count == 0
+ assert example01_class.getCount() == 0
+
+ pl = payload_class(3.14)
+ pl_a = example01_class.staticCyclePayload(pl, 66.)
+ pl_a.getData() == 66.
+ assert payload_class.count == 1
+ pl = None
+ gc.collect()
+ assert payload_class.count == 0
+
+ # TODO: need ReferenceError on touching pl_a
More information about the pypy-commit
mailing list