[pypy-commit] pypy reflex-support: nicer template support
wlav
noreply at buildbot.pypy.org
Wed Jun 8 01:41:12 CEST 2011
Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r44823:cd3befebf2f2
Date: 2011-06-07 12:02 -0700
http://bitbucket.org/pypy/pypy/changeset/cd3befebf2f2/
Log: nicer template support
diff --git a/pypy/module/cppyy/__init__.py b/pypy/module/cppyy/__init__.py
--- a/pypy/module/cppyy/__init__.py
+++ b/pypy/module/cppyy/__init__.py
@@ -6,6 +6,7 @@
interpleveldefs = {
'_load_lib' : 'interp_cppyy.load_lib',
'_type_byname' : 'interp_cppyy.type_byname',
+ '_template_byname' : 'interp_cppyy.template_byname',
}
appleveldefs = {
diff --git a/pypy/module/cppyy/capi.py b/pypy/module/cppyy/capi.py
--- a/pypy/module/cppyy/capi.py
+++ b/pypy/module/cppyy/capi.py
@@ -33,6 +33,11 @@
[rffi.CCHARP], C_TYPEHANDLE,
compilation_info=eci)
+c_get_templatehandle = rffi.llexternal(
+ "cppyy_get_templatehandle",
+ [rffi.CCHARP], C_TYPEHANDLE,
+ compilation_info=eci)
+
c_allocate = rffi.llexternal(
"cppyy_allocate",
[C_TYPEHANDLE], rffi.VOIDP,
diff --git a/pypy/module/cppyy/include/cppyy.h b/pypy/module/cppyy/include/cppyy.h
--- a/pypy/module/cppyy/include/cppyy.h
+++ b/pypy/module/cppyy/include/cppyy.h
@@ -7,5 +7,6 @@
#include "Reflex/Object.h"
#include "Reflex/Builder/TypeBuilder.h"
#include "Reflex/PropertyList.h"
+#include "Reflex/TypeTemplate.h"
#endif // CPPYY_CPPYY
diff --git a/pypy/module/cppyy/include/reflexcwrapper.h b/pypy/module/cppyy/include/reflexcwrapper.h
--- a/pypy/module/cppyy/include/reflexcwrapper.h
+++ b/pypy/module/cppyy/include/reflexcwrapper.h
@@ -1,4 +1,3 @@
-
#ifndef CPPYY_REFLEXCWRAPPER
#define CPPYY_REFLEXCWRAPPER
@@ -11,6 +10,7 @@
/* name to handle */
cppyy_typehandle_t cppyy_get_typehandle(const char* class_name);
+ cppyy_typehandle_t cppyy_get_templatehandle(const char* template_name);
/* memory management */
void* cppyy_allocate(cppyy_typehandle_t handle);
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
@@ -48,6 +48,22 @@
raise OperationError(space.w_TypeError, space.wrap(str("no such C++ class %s" % name)))
type_byname.unwrap_spec = [ObjSpace, str]
+def template_byname(space, name):
+ state = space.fromcache(State)
+ try:
+ return state.cpptype_cache[name]
+ except KeyError:
+ pass
+
+ handle = capi.c_get_templatehandle(name)
+ if handle:
+ template = W_CPPTemplateType(space, name, handle)
+ state.cpptype_cache[name] = template
+ return template
+
+ raise OperationError(space.w_TypeError, space.wrap(str("no such C++ template %s" % name)))
+template_byname.unwrap_spec = [ObjSpace, str]
+
class W_CPPLibrary(Wrappable):
_immutable_ = True
@@ -459,6 +475,24 @@
)
+class W_CPPTemplateType(Wrappable):
+ _immutable_fields_ = ["name", "handle"]
+
+ def __init__(self, space, name, handle):
+ self.space = space
+ self.name = name
+ self.handle = handle
+
+ def __call__(self, args_w):
+ fullname = "".join([self.name, '<', self.space.str_w(args_w[0]), '>'])
+ return type_byname(self.space, fullname)
+
+W_CPPTemplateType.typedef = TypeDef(
+ 'CPPTemplateType',
+ __call__ = interp2app(W_CPPTemplateType.__call__, unwrap_spec=['self', 'args_w']),
+)
+
+
class W_CPPInstance(Wrappable):
_immutable_fields_ = ["cppclass"]
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
@@ -12,6 +12,16 @@
class CppyyClass(type):
pass
+
+class CppyyTemplateType(object):
+ def __init__(self, scope, name):
+ self._scope = scope
+ self._name = name
+
+ def __call__(self, *args):
+ fullname = "".join([self._name, '<', str(args[0]), '>'])
+ return getattr(self._scope, fullname)
+
class CppyyObject(object):
__metaclass__ = CppyyClass
@@ -56,14 +66,14 @@
def __innercpp_getattr__(self, attr):
try:
- cppclass = get_cppitem(attr, self.__name__)
+ cppclass = get_cppitem(attr, self)
self.__dict__[attr] = cppclass
return cppclass
except TypeError:
raise AttributeError("%s object has no attribute '%s'" % (self,attr))
-def make_cppnamespace(name, cppns):
+def make_cppnamespace(namespace_name, cppns):
d = {}
# insert static methods into the "namespace" dictionary
@@ -72,7 +82,7 @@
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),),
+ metans = type(CppyyNamespace)(namespace_name+'_meta', (type(type),),
{"__getattr__" : __innercpp_getattr__})
# add all data members to the dictionary of the class to be created, and
@@ -83,10 +93,10 @@
setattr(metans, dm, cppdm)
# create the python-side C++ namespace representation
- pycppns = metans(name, (type,), d)
+ pycppns = metans(namespace_name, (type,), d)
# cache result and return
- _existing_cppitems[name] = pycppns
+ _existing_cppitems[namespace_name] = pycppns
return pycppns
def make_cppclass(class_name, cpptype):
@@ -127,11 +137,14 @@
return pycpptype
+def make_cpptemplatetype(template_name, scope):
+ return CppyyTemplateType(scope, template_name)
+
_existing_cppitems = {} # to merge with gbl.__dict__ (?)
-def get_cppitem(name, scope=""):
+def get_cppitem(name, scope=None):
if scope:
- fullname = scope+"::"+name
+ fullname = scope.__name__+"::"+name
else:
fullname = name
@@ -142,11 +155,24 @@
pass
# ... if lookup failed, create
- cppitem = cppyy._type_byname(fullname)
- if cppitem.is_namespace():
- return make_cppnamespace(fullname, cppitem)
- else:
- return make_cppclass(fullname, cppitem)
+ pycppitem = None
+ try:
+ cppitem = cppyy._type_byname(fullname)
+ if cppitem.is_namespace():
+ pycppitem = make_cppnamespace(fullname, cppitem)
+ else:
+ pycppitem = make_cppclass(fullname, cppitem)
+ except TypeError:
+ cppitem = cppyy._template_byname(fullname)
+ pycppitem = make_cpptemplatetype(name, scope)
+
+ if pycppitem:
+ _existing_cppitems[fullname] = pycppitem
+ return pycppitem
+
+ raise AttributeError("'%s' has no attribute '%s'", (str(scope), name))
+
+
get_cppclass = get_cppitem # TODO: restrict to classes only (?)
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
@@ -24,7 +24,12 @@
/* name to handle --------------------------------------------------------- */
cppyy_typehandle_t cppyy_get_typehandle(const char* class_name) {
Reflex::Scope s = Reflex::Scope::ByName(class_name);
- return Reflex::Scope::ByName(class_name).Id();
+ return s.Id();
+}
+
+cppyy_typehandle_t cppyy_get_templatehandle(const char* template_name) {
+ Reflex::TypeTemplate tt = Reflex::TypeTemplate::ByName(template_name);
+ return tt.Id();
}
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
@@ -30,15 +30,21 @@
import cppyy
assert cppyy.gbl.std is cppyy.gbl.std
-# assert cppyy.gbl.std.vector is cppyy.gbl.std.vector
+ assert cppyy.gbl.std.vector is cppyy.gbl.std.vector
- tv = getattr(cppyy.gbl.std,'vector<int>')
+ assert callable(cppyy.gbl.std.vector)
- v = tv()
+ tv1 = getattr(cppyy.gbl.std,'vector<int>')
+ tv2 = cppyy.gbl.std.vector('int')
+
+ assert tv1 is tv2
+
+ v = tv1()
for i in range(self.N):
v.push_back(i)
assert v.size() == i+1
# assert v[i] == i
-# assert len(v) == self.N
+ assert v.size() == self.N
+# assert len(v) == self.N
v.destruct()
More information about the pypy-commit
mailing list