Author: Wim Lavrijsen <[email protected]>
Branch: reflex-support
Changeset: r44615:7e43dd48bcb1
Date: 2011-05-31 13:19 -0700
http://bitbucket.org/pypy/pypy/changeset/7e43dd48bcb1/
Log: pull C++ bound methods into the app level to allow normal python mro
to work
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
@@ -332,17 +332,26 @@
@jit.purefunction
def get_overload(self, name):
- return self.methods[name]
+ try:
+ return self.methods[name]
+ except KeyError:
+ raise OperationError(
+ self.space.w_AttributeError,
+ self.space.wrap(str("class %s has no attribute %s" %
(self.name, name))))
def get_data_member_names(self):
return self.space.newlist([self.space.wrap(name) for name in
self.data_members])
@jit.purefunction
def get_data_member(self, name):
- return self.data_members[name]
+ try:
+ return self.data_members[name]
+ except KeyError:
+ raise OperationError(
+ self.space.w_AttributeError,
+ self.space.wrap(str("class %s has no attribute %s" %
(self.name, name))))
- def invoke(self, name, args_w):
- overload = self.get_overload(name)
+ def invoke(self, overload, args_w):
return overload.call(NULL_VOIDP, args_w)
W_CPPScope.typedef = TypeDef(
@@ -351,7 +360,7 @@
get_overload = interp2app(W_CPPScope.get_overload, unwrap_spec=['self',
str]),
get_data_member_names = interp2app(W_CPPScope.get_data_member_names,
unwrap_spec=['self']),
get_data_member = interp2app(W_CPPScope.get_data_member,
unwrap_spec=['self', str]),
- invoke = interp2app(W_CPPScope.invoke, unwrap_spec=['self', str,
'args_w']),
+ invoke = interp2app(W_CPPScope.invoke, unwrap_spec=['self', W_CPPOverload,
'args_w']),
)
@@ -443,7 +452,7 @@
get_data_member_names = interp2app(W_CPPType.get_data_member_names,
unwrap_spec=['self']),
get_data_member = interp2app(W_CPPType.get_data_member,
unwrap_spec=['self', str]),
is_namespace = interp2app(W_CPPType.is_namespace, unwrap_spec=['self']),
- invoke = interp2app(W_CPPType.invoke, unwrap_spec=['self', str, 'args_w']),
+ invoke = interp2app(W_CPPType.invoke, unwrap_spec=['self', W_CPPOverload,
'args_w']),
construct = interp2app(W_CPPType.construct, unwrap_spec=['self',
'args_w']),
)
@@ -460,10 +469,9 @@
if not self.rawobject:
raise OperationError(self.space.w_ReferenceError,
self.space.wrap("trying to access a NULL pointer"))
- def invoke(self, method_name, args_w):
+ def invoke(self, overload, args_w):
self._nullcheck()
cppclass = jit.hint(self.cppclass, promote=True)
- overload = cppclass.get_overload(method_name)
return overload.call(self.rawobject, args_w)
def destruct(self):
@@ -472,6 +480,6 @@
W_CPPInstance.typedef = TypeDef(
'CPPInstance',
- invoke = interp2app(W_CPPInstance.invoke, unwrap_spec=['self', str,
'args_w']),
+ invoke = interp2app(W_CPPInstance.invoke, unwrap_spec=['self',
W_CPPOverload, 'args_w']),
destruct = interp2app(W_CPPInstance.destruct, unwrap_spec=['self']),
)
diff --git a/pypy/module/cppyy/pythonify.py b/pypy/module/cppyy/pythonify.py
--- a/pypy/module/cppyy/pythonify.py
+++ b/pypy/module/cppyy/pythonify.py
@@ -29,27 +29,28 @@
bound_obj._cppinstance = cppobj
return bound_obj
-def make_static_function(cpptype, name, rettype):
- print rettype
+def make_static_function(cpptype, func_name, cppol):
+ rettype = cppol.get_returntype()
if not rettype: # return builtin type
def method(*args):
- return cpptype.invoke(name, *args)
+ return cpptype.invoke(cppol, *args)
else: # return instance
cppclass = get_cppclass(rettype)
def method(*args):
- return bind_object(cpptype.invoke(name, *args), cppclass)
- method.__name__ = name
+ return bind_object(cpptype.invoke(cppol, *args), cppclass)
+ method.__name__ = func_name
return staticmethod(method)
-def make_method(name, rettype):
+def make_method(meth_name, cppol):
+ rettype = cppol.get_returntype()
if not rettype: # return builtin type
def method(self, *args):
- return self._cppinstance.invoke(name, *args)
+ return self._cppinstance.invoke(cppol, *args)
else: # return instance
cppclass = get_cppclass(rettype)
def method(self, *args):
- return bind_object(self._cppinstance.invoke(name, *args), cppclass)
- method.__name__ = name
+ return bind_object(self._cppinstance.invoke(cppol, *args),
cppclass)
+ method.__name__ = meth_name
return method
@@ -68,9 +69,9 @@
d = {}
# insert static methods into the "namespace" dictionary
- for f in cppns.get_method_names():
+ for func_name in cppns.get_method_names():
cppol = cppns.get_overload(f)
- d[f] = make_static_function(cppns, f, cppol.get_returntype())
+ d[func_name] = make_static_function(cppns, func_name, cppol)
# create a meta class to allow properties (for static data write access)
metans = type(CppyyNamespace)(name+'_meta', (type(type),),
@@ -90,16 +91,16 @@
_existing_cppitems[name] = pycppns
return pycppns
-def make_cppclass(name, cpptype):
+def make_cppclass(class_name, cpptype):
d = {"_cppyyclass" : cpptype}
# insert (static) methods into the class dictionary
- for f in cpptype.get_method_names():
- cppol = cpptype.get_overload(f)
+ for meth_name in cpptype.get_method_names():
+ cppol = cpptype.get_overload(meth_name)
if cppol.is_static():
- d[f] = make_static_function(cpptype, f, cppol.get_returntype())
+ d[meth_name] = make_static_function(cpptype, meth_name, cppol)
else:
- d[f] = make_method(f, cppol.get_returntype())
+ d[meth_name] = make_method(meth_name, cppol)
# get a list of base classes for class creation
bases = tuple([get_cppclass(base) for base in cpptype.get_base_names()])
@@ -108,23 +109,23 @@
# create a meta class to allow properties (for static data write access)
metabases = tuple([type(base) for base in bases])
- metacpp = type(CppyyClass)(name+'_meta', metabases,
+ metacpp = type(CppyyClass)(class_name+'_meta', metabases,
{"__getattr__" : __innercpp_getattr__})
# add all data members to the dictionary of the class to be created, and
# static ones also to the meta class (needed for property setters)
- for dm in cpptype.get_data_member_names():
- cppdm = cpptype.get_data_member(dm)
+ for dm_name in cpptype.get_data_member_names():
+ cppdm = cpptype.get_data_member(dm_name)
- d[dm] = cppdm
+ d[dm_name] = cppdm
if cppdm.is_static():
- setattr(metacpp, dm, cppdm)
+ setattr(metacpp, dm_name, cppdm)
# create the python-side C++ class representation
- pycpptype = metacpp(name, bases, d)
+ pycpptype = metacpp(class_name, bases, d)
# cache result and return
- _existing_cppitems[name] = pycpptype
+ _existing_cppitems[class_name] = pycpptype
return pycpptype
diff --git a/pypy/module/cppyy/test/advancedcpp.h
b/pypy/module/cppyy/test/advancedcpp.h
--- a/pypy/module/cppyy/test/advancedcpp.h
+++ b/pypy/module/cppyy/test/advancedcpp.h
@@ -4,23 +4,25 @@
//===========================================================================
class base_class { // for simple inheritance testing
public:
- base_class() { m_a = 1; m_da = 1.1; }
+ base_class() { m_b = 1; m_db = 1.1; }
virtual ~base_class() {}
- virtual int get_value() = 0;
+ virtual int get_value() { return m_b; }
+ double get_base_value() { return m_db; }
public:
- int m_a;
- double m_da;
+ int m_b;
+ double m_db;
};
class derived_class : public base_class {
public:
- derived_class() { m_b = 2; m_db = 2.2;}
- virtual int get_value() { return m_b; }
+ derived_class() { m_d = 2; m_dd = 2.2;}
+ virtual int get_value() { return m_d; }
+ double get_derived_value() { return m_dd; }
public:
- int m_b;
- double m_db;
+ int m_d;
+ double m_dd;
};
diff --git a/pypy/module/cppyy/test/bench1.py b/pypy/module/cppyy/test/bench1.py
--- a/pypy/module/cppyy/test/bench1.py
+++ b/pypy/module/cppyy/test/bench1.py
@@ -10,11 +10,14 @@
for i in range(10000000):
i
+addDataToInt = cls.get_overload("addDataToInt")
+
def f():
res = 0
for i in range(10000000):
- #inst.invoke("addDataToDouble", float(i))
- inst.invoke("addDataToInt", i)
+ #inst.invoke(cls.get_overload("addDataToDouble"), float(i))
+ #inst.invoke(cls.get_overload("addDataToInt"), i)
+ inst.invoke(addDataToInt, i)
g(); f();
t1 = time.time()
diff --git a/pypy/module/cppyy/test/test_advancedcpp.py
b/pypy/module/cppyy/test/test_advancedcpp.py
--- a/pypy/module/cppyy/test/test_advancedcpp.py
+++ b/pypy/module/cppyy/test/test_advancedcpp.py
@@ -33,11 +33,22 @@
assert issubclass(derived_class, base_class)
assert not issubclass(base_class, derived_class)
- c = derived_class()
- assert isinstance( c, derived_class )
- assert isinstance( c, base_class )
+ b = base_class()
+ assert isinstance(b, base_class)
+ assert not isinstance(b, derived_class)
- c.destruct()
+ assert b.get_value() == 1
+ assert b.get_base_value() == 1.1
+
+ d = derived_class()
+ assert isinstance(d, derived_class)
+ assert isinstance(d, base_class)
+
+ assert d.get_value() == 2
+ assert d.get_base_value() == 1.1
+ assert d.get_derived_value() == 2.2
+
+ d.destruct()
def test02_namespaces(self):
"""Test access to namespaces and inner classes"""
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
@@ -39,136 +39,143 @@
def test_example01static_int(self):
"""Test passing of an int, returning of an int, and overloading on a
differening number of arguments."""
+
import sys
t = self.example01
- res = t.invoke("staticAddOneToInt", 1)
+
+ res = t.invoke(t.get_overload("staticAddOneToInt"), 1)
assert res == 2
- res = t.invoke("staticAddOneToInt", 1L)
+ res = t.invoke(t.get_overload("staticAddOneToInt"), 1L)
assert res == 2
- res = t.invoke("staticAddOneToInt", 1, 2)
+ res = t.invoke(t.get_overload("staticAddOneToInt"), 1, 2)
assert res == 4
- res = t.invoke("staticAddOneToInt", -1)
+ res = t.invoke(t.get_overload("staticAddOneToInt"), -1)
assert res == 0
- res = t.invoke("staticAddOneToInt", sys.maxint-1)
+ res = t.invoke(t.get_overload("staticAddOneToInt"), sys.maxint-1)
assert res == sys.maxint
- res = t.invoke("staticAddOneToInt", sys.maxint)
+ res = t.invoke(t.get_overload("staticAddOneToInt"), sys.maxint)
assert res == -sys.maxint-1
- raises(TypeError, 't.invoke("staticAddOneToInt", 1, [])')
- raises(TypeError, 't.invoke("staticAddOneToInt", 1.)')
- raises(OverflowError, 't.invoke("staticAddOneToInt", sys.maxint+1)')
+ raises(TypeError, 't.invoke(t.get_overload("staticAddOneToInt"), 1,
[])')
+ raises(TypeError, 't.invoke(t.get_overload("staticAddOneToInt"), 1.)')
+ raises(OverflowError, 't.invoke(t.get_overload("staticAddOneToInt"),
sys.maxint+1)')
def test_example01static_double(self):
"""Test passing of a double and returning of a double on a static
function."""
+
t = self.example01
- res = t.invoke("staticAddToDouble", 0.09)
+
+ res = t.invoke(t.get_overload("staticAddToDouble"), 0.09)
assert res == 0.09 + 0.01
def test_example01static_constcharp(self):
"""Test passing of a C string and returning of a C string on a static
function."""
+
t = self.example01
- res = t.invoke("staticAtoi", "1")
+
+ res = t.invoke(t.get_overload("staticAtoi"), "1")
assert res == 1
-
- res = t.invoke("staticStrcpy", "aap")
+ res = t.invoke(t.get_overload("staticStrcpy"), "aap")
+ assert res == "aap"
+ res = t.invoke(t.get_overload("staticStrcpy"), u"aap")
assert res == "aap"
- res = t.invoke("staticStrcpy", u"aap")
- assert res == "aap"
-
- raises(TypeError, 't.invoke("staticStrcpy", 1.)')
+ raises(TypeError, 't.invoke(t.get_overload("staticStrcpy"), 1.)')
def test_example01method_int(self):
"""Test passing of a int, returning of a int, and memory cleanup, on
a method."""
+
t = self.example01
- assert t.invoke("getCount") == 0
- instance = t.construct(7)
- assert t.invoke("getCount") == 1
- res = instance.invoke("addDataToInt", 4)
+
+ 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 = instance.invoke("addDataToInt", -4)
+ res = e1.invoke(t.get_overload("addDataToInt"), -4)
assert res == 3
- instance.destruct()
- assert t.invoke("getCount") == 0
- raises(ReferenceError, 'instance.invoke("addDataToInt", 4)')
+ e1.destruct()
+ assert t.invoke(t.get_overload("getCount")) == 0
+ raises(ReferenceError, 'e1.invoke(t.get_overload("addDataToInt"), 4)')
- instance = t.construct(7)
- instance2 = t.construct(8)
- assert t.invoke("getCount") == 2
- instance.destruct()
- assert t.invoke("getCount") == 1
- instance2.destruct()
- assert t.invoke("getCount") == 0
+ e1 = t.construct(7)
+ e2 = t.construct(8)
+ assert t.invoke(t.get_overload("getCount")) == 2
+ e1.destruct()
+ assert t.invoke(t.get_overload("getCount")) == 1
+ e2.destruct()
+ 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"""
+
t = self.example01
- instance = t.construct(13)
- res = instance.invoke("addDataToDouble", 16)
+
+ e = t.construct(13)
+ res = e.invoke(t.get_overload("addDataToDouble"), 16)
assert round(res-29, 8) == 0.
- instance.destruct()
- instance = t.construct(-13)
- res = instance.invoke("addDataToDouble", 16)
+ e.destruct()
+
+ e = t.construct(-13)
+ res = e.invoke(t.get_overload("addDataToDouble"), 16)
assert round(res-3, 8) == 0.
- instance.destruct()
- assert t.invoke("getCount") == 0
+ e.destruct()
+ assert t.invoke(t.get_overload("getCount")) == 0
def test_example01method_constcharp(self):
"""Test passing of a C string and returning of a C string on a
method."""
t = self.example01
- instance = t.construct(42)
- res = instance.invoke("addDataToAtoi", "13")
+ e = t.construct(42)
+ res = e.invoke(t.get_overload("addDataToAtoi"), "13")
assert res == 55
-
- res = instance.invoke("addToStringValue", "12")
+ res = e.invoke(t.get_overload("addToStringValue"), "12")
assert res == "54"
- res = instance.invoke("addToStringValue", "-12")
+ res = e.invoke(t.get_overload("addToStringValue"), "-12")
assert res == "30"
- instance.destruct()
- assert t.invoke("getCount") == 0
+ e.destruct()
+ assert t.invoke(t.get_overload("getCount")) == 0
def testPassingOfAnObjectByPointer(self):
"""Test passing of an instance as an argument."""
- t = self.example01
+ t1 = self.example01
+ t2 = self.payload
- pl = self.payload.construct(3.14)
- assert round(pl.invoke("getData")-3.14, 8) == 0
-
- t.invoke("staticSetPayload", pl, 41.) # now pl is a CPPInstance
- assert pl.invoke("getData") == 41.
+ pl = t2.construct(3.14)
+ assert round(pl.invoke(t2.get_overload("getData"))-3.14, 8) == 0
+ t1.invoke(t1.get_overload("staticSetPayload"), pl, 41.) # now pl is a
CPPInstance
+ assert pl.invoke(t2.get_overload("getData")) == 41.
- e = t.construct(50)
- e.invoke("setPayload", pl);
- assert round(pl.invoke("getData")-50., 8) == 0
+ e = t1.construct(50)
+ e.invoke(t1.get_overload("setPayload"), pl);
+ assert round(pl.invoke(t2.get_overload("getData"))-50., 8) == 0
e.destruct()
pl.destruct()
- assert t.invoke("getCount") == 0
+ assert t1.invoke(t1.get_overload("getCount")) == 0
def testReturningOfAnObjectByPointer(self):
"""Test returning of an instance as an argument."""
- t = self.example01
-
- pl = self.payload.construct(3.14)
- assert round(pl.invoke("getData")-3.14, 8) == 0
+ t1 = self.example01
+ t2 = self.payload
- pl2 = t.invoke("staticCyclePayload", pl, 38.)
- assert pl2.invoke("getData") == 38.
+ pl1 = t2.construct(3.14)
+ assert round(pl1.invoke(t2.get_overload("getData"))-3.14, 8) == 0
+ pl2 = t1.invoke(t1.get_overload("staticCyclePayload"), pl1, 38.)
+ assert pl2.invoke(t2.get_overload("getData")) == 38.
- e = t.construct(50)
-
- pl2 = e.invoke("cyclePayload", pl);
- assert round(pl2.invoke("getData")-50., 8) == 0
+ e = t1.construct(50)
+ pl2 = e.invoke(t1.get_overload("cyclePayload"), pl1);
+ assert round(pl2.invoke(t2.get_overload("getData"))-50., 8) == 0
e.destruct()
- pl.destruct()
- assert t.invoke("getCount") == 0
-
+ pl1.destruct()
+ assert t1.invoke(t1.get_overload("getCount")) == 0
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit