[pypy-svn] r76017 - in pypy/branch/reflex-support/pypy/module/cppyy: . test
wlav at codespeak.net
wlav at codespeak.net
Thu Jul 8 12:38:19 CEST 2010
Author: wlav
Date: Thu Jul 8 12:38:17 2010
New Revision: 76017
Modified:
pypy/branch/reflex-support/pypy/module/cppyy/__init__.py
pypy/branch/reflex-support/pypy/module/cppyy/interp_cppyy.py
pypy/branch/reflex-support/pypy/module/cppyy/pythonify.py
pypy/branch/reflex-support/pypy/module/cppyy/test/test_cppyy.py
pypy/branch/reflex-support/pypy/module/cppyy/test/test_pythonify.py
Log:
(wlav, cfbolz): start exposing c++ classes and support static methods on them.
Modified: pypy/branch/reflex-support/pypy/module/cppyy/__init__.py
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/__init__.py (original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/__init__.py Thu Jul 8 12:38:17 2010
@@ -4,7 +4,8 @@
""" """
interpleveldefs = {
- '_load_lib': 'interp_cppyy.load_lib',
+ '_load_lib' : 'interp_cppyy.load_lib',
+ '_type_byname' : 'interp_cppyy.type_byname',
}
appleveldefs = {
Modified: pypy/branch/reflex-support/pypy/module/cppyy/interp_cppyy.py
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/interp_cppyy.py (original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/interp_cppyy.py Thu Jul 8 12:38:17 2010
@@ -20,19 +20,22 @@
return W_CPPLibrary(space, cdll)
load_lib.unwrap_spec = [ObjSpace, str]
+def type_byname(space, name):
+ handle = capi.c_cppyy_get_typehandle(name)
+ if handle:
+ return W_CPPType(space, name, handle)
+ raise OperationError(space.w_TypeError, space.wrap("no such C++ class %s" % name))
+type_byname.unwrap_spec = [ObjSpace, str]
+
+
class W_CPPLibrary(Wrappable):
_immutable_ = True
def __init__(self, space, cdll):
self.cdll = cdll
self.space = space
- def type_byname(self, name):
- handle = capi.c_cppyy_get_typehandle(name)
- return W_CPPType(self, name, handle)
-
W_CPPLibrary.typedef = TypeDef(
'CPPLibrary',
- type_byname = interp2app(W_CPPLibrary.type_byname, unwrap_spec=['self', str]),
)
class CPPMethod(object):
@@ -118,7 +121,7 @@
return W_CPPObject(self.cpptype, result)
-class CPPOverload(object):
+class W_CPPOverload(Wrappable):
_immutable_ = True
_immutable_fields_ = ["functions[*]"]
def __init__(self, space, func_name, functions):
@@ -126,6 +129,9 @@
self.func_name = func_name
self.functions = debug.make_sure_not_resized(functions)
+ def is_static(self):
+ return self.space.wrap(isinstance(self.functions[0], CPPFunction))
+
@jit.unroll_safe
def call(self, cppthis, args_w):
space = self.space
@@ -142,15 +148,19 @@
raise OperationError(space.w_TypeError, space.wrap("none of the overloads matched"))
def __repr__(self):
- return "CPPOverload(%s, %s)" % (self.func_name, self.functions)
+ return "W_CPPOverload(%s, %s)" % (self.func_name, self.functions)
+
+W_CPPOverload.typedef = TypeDef(
+ 'CPPOverload',
+ is_static = interp2app(W_CPPOverload.is_static, unwrap_spec=['self']),
+)
class W_CPPType(Wrappable):
- _immutable_fields_ = ["cpplib", "name","handle"]
+ _immutable_fields_ = ["name","handle"]
- def __init__(self, cpplib, name, handle):
- self.space = cpplib.space
- self.cpplib = cpplib
+ def __init__(self, space, name, handle):
+ self.space = space
self.name = name
self.handle = handle
self.function_members = {}
@@ -165,7 +175,7 @@
overload = args_temp.setdefault(func_member_name, [])
overload.append(cppfunction)
for name, functions in args_temp.iteritems():
- overload = CPPOverload(self.space, name, functions[:])
+ overload = W_CPPOverload(self.space, name, functions[:])
self.function_members[name] = overload
def _make_cppfunction(self, method_index):
@@ -183,6 +193,9 @@
cls = CPPMethod
return cls(self, method_index, result_type, argtypes)
+ def get_function_members(self):
+ return self.space.newlist([self.space.wrap(name) for name in self.function_members])
+
@jit.purefunction
def get_overload(self, name):
return self.function_members[name]
@@ -197,6 +210,8 @@
W_CPPType.typedef = TypeDef(
'CPPType',
+ get_function_members = interp2app(W_CPPType.get_function_members, unwrap_spec=['self']),
+ get_overload = interp2app(W_CPPType.get_overload, unwrap_spec=['self', str]),
invoke = interp2app(W_CPPType.invoke, unwrap_spec=['self', str, 'args_w']),
construct = interp2app(W_CPPType.construct, unwrap_spec=['self', 'args_w']),
)
Modified: pypy/branch/reflex-support/pypy/module/cppyy/pythonify.py
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/pythonify.py (original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/pythonify.py Thu Jul 8 12:38:17 2010
@@ -1,25 +1,52 @@
# NOT_RPYTHON
import cppyy
-class _gbl(object):
- """Global C++ namespace, i.e. ::."""
-
- def __getattr__(self, attr):
- raise AttributeError
-class CppyyClass(object):
- def __init__(self, cppclass):
- # fill dictionary
- pass
+class CppyyClass(type):
+ pass
+def make_static_function(cpptype, name):
+ def method(*args):
+ return cpptype.invoke(name,*args)
+ method.__name__ = name
+ return staticmethod(method)
+_existing_classes = {}
def get_cppclass(name):
# lookup class
+ try:
+ return _existing_classes[name]
+ except KeyError:
+ pass
# if failed, create
+ # TODO: handle base classes
+ cpptype = cppyy._type_byname(name)
+ d = {"_cppyyclass" : cpptype}
+ for f in cpptype.get_function_members():
+ cppol = cpptype.get_overload(f)
+ if cppol.is_static():
+ d[f] = make_static_function(cpptype, f)
+ else:
+ pass
+
+ pycpptype = CppyyClass(name, (object,), d)
- # create base classes
- pass
+ return pycpptype
+
+# raise TypeError("no such C++ class %s" % name)
+
+
+class _gbl(object):
+ """Global C++ namespace, i.e. ::."""
+
+ def __getattr__(self, attr):
+ try:
+ cppclass = get_cppclass(attr)
+ self.__dict__[attr] = cppclass
+ return cppclass
+ except TypeError:
+ raise AttributeError("'gbl' object has no attribute '%s'" % attr)
_loaded_shared_libs = {}
Modified: pypy/branch/reflex-support/pypy/module/cppyy/test/test_cppyy.py
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/test/test_cppyy.py (original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/test/test_cppyy.py Thu Jul 8 12:38:17 2010
@@ -14,7 +14,7 @@
class TestCPPYYImplementation:
def test_class_query(self):
lib = interp_cppyy.load_lib(space, shared_lib)
- w_cppyyclass = lib.type_byname("example01")
+ w_cppyyclass = interp_cppyy.type_byname(space, "example01")
adddouble = w_cppyyclass.function_members["staticAddToDouble"]
func, = adddouble.functions
assert isinstance(func.executor, executor.DoubleExecutor)
@@ -27,13 +27,14 @@
env = os.environ
cls.w_example01 = cls.space.appexec([], """():
import cppyy
- return cppyy.load_lib(%r)""" % (shared_lib, ))
+ cppyy.load_lib(%r)
+ return cppyy._type_byname('example01')""" % (shared_lib, ))
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.type_byname("example01")
+ t = self.example01
res = t.invoke("staticAddOneToInt", 1)
assert res == 2
res = t.invoke("staticAddOneToInt", 1L)
@@ -54,14 +55,14 @@
def test_example01static_double(self):
"""Test passing of a double and returning of a double on a static function."""
- t = self.example01.type_byname("example01")
+ t = self.example01
res = t.invoke("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.type_byname("example01")
+ t = self.example01
res = t.invoke("staticAtoi", "1")
assert res == 1
@@ -76,7 +77,7 @@
def test_example01method_int(self):
"""Test passing of a int, returning of a int, and memory cleanup, on
a method."""
- t = self.example01.type_byname("example01")
+ t = self.example01
assert t.invoke("getCount") == 0
instance = t.construct(7)
assert t.invoke("getCount") == 1
@@ -98,7 +99,7 @@
def test_example01method_double(self):
"""Test passing of a double and returning of double on a method"""
- t = self.example01.type_byname("example01")
+ t = self.example01
instance = t.construct(13)
res = instance.invoke("addDataToDouble", 16)
assert round(res-29, 8) == 0.
@@ -110,7 +111,7 @@
"""Test passing of a C string and returning of a C string on a
method."""
- t = self.example01.type_byname("example01")
+ t = self.example01
instance = t.construct(42)
res = instance.invoke("addDataToAtoi", "13")
Modified: pypy/branch/reflex-support/pypy/module/cppyy/test/test_pythonify.py
==============================================================================
--- pypy/branch/reflex-support/pypy/module/cppyy/test/test_pythonify.py (original)
+++ pypy/branch/reflex-support/pypy/module/cppyy/test/test_pythonify.py Thu Jul 8 12:38:17 2010
@@ -25,3 +25,35 @@
import cppyy
lib2 = cppyy.load_lib(self.shared_lib)
assert self.example01 is lib2
+
+ def testFindingAClass(self):
+ """Test the lookup of a class, and its caching."""
+ import cppyy
+ example01_class = cppyy.gbl.example01
+ cl2 = cppyy.gbl.example01
+ assert example01_class is cl2
+
+ raises(AttributeError, "cppyy.gbl.nonexistingclass")
+
+ def testCallingAStaticFunction(self):
+ """Test calling of static methods."""
+ import cppyy, sys
+ example01_class = cppyy.gbl.example01
+ res = example01_class.staticAddOneToInt(1)
+ assert res == 2
+
+ res = example01_class.staticAddOneToInt(1L)
+ assert res == 2
+ res = example01_class.staticAddOneToInt(1, 2)
+ assert res == 4
+ res = example01_class.staticAddOneToInt(-1)
+ assert res == 0
+ res = example01_class.staticAddOneToInt(sys.maxint-1)
+ assert res == sys.maxint
+ res = example01_class.staticAddOneToInt(sys.maxint)
+ assert res == -sys.maxint-1
+
+ raises(TypeError, 'example01_class.staticAddOneToInt(1, [])')
+ raises(TypeError, 'example01_class.staticAddOneToInt(1.)')
+ raises(OverflowError, 'example01_class.staticAddOneToInt(sys.maxint+1)')
+
More information about the Pypy-commit
mailing list