Author: Wim Lavrijsen <wlavrij...@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() _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit