Author: Wim Lavrijsen <[email protected]>
Branch: reflex-support
Changeset: r44560:dc3b3a380dcd
Date: 2011-05-27 17:37 -0700
http://bitbucket.org/pypy/pypy/changeset/dc3b3a380dcd/

Log:    initial support for classes in namespaces

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
@@ -48,6 +48,17 @@
     compilation_info=eci)
 
 
+c_is_namespace = rffi.llexternal(
+    "cppyy_is_namespace",
+    [C_TYPEHANDLE], rffi.INT,
+    compilation_info=eci)
+
+
+c_final_name = rffi.llexternal(
+    "cppyy_final_name",
+    [C_TYPEHANDLE], rffi.CCHARP,
+    compilation_info=eci)
+
 c_num_bases = rffi.llexternal(
     "cppyy_num_bases",
     [C_TYPEHANDLE], rffi.INT,
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
@@ -28,7 +28,11 @@
 
     cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_typehandle_t handle, 
int method_index);
 
+    /* scope reflection information 
------------------------------------------- */
+    int cppyy_is_namespace(cppyy_typehandle_t handle);
+
     /* type/class reflection information 
-------------------------------------- */
+    char* cppyy_final_name(cppyy_typehandle_t handle);
     int cppyy_num_bases(cppyy_typehandle_t handle);
     char* cppyy_base_name(cppyy_typehandle_t handle, int base_index);
     int cppyy_is_subtype(cppyy_typehandle_t h1, cppyy_typehandle_t h2);
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
@@ -24,7 +24,7 @@
 
 class State(object):
     def __init__(self, space):
-        self.cpptype_cache = {}
+        self.cpptype_cache = { "void" : W_CPPType(space, "void", NULL_VOIDP) }
 
 def type_byname(space, name):
     state = space.fromcache(State)
@@ -35,7 +35,11 @@
 
     handle = capi.c_get_typehandle(name)
     if handle:
-        cpptype = W_CPPType(space, name, handle)
+        final_name = capi.charp2str_free(capi.c_final_name(handle))
+        if capi.c_is_namespace(handle):
+            cpptype = W_CPPNamespace(space, final_name, handle)
+        else:
+            cpptype = W_CPPType(space, final_name, handle)
         state.cpptype_cache[name] = cpptype
         cpptype._find_methods()
         cpptype._find_data_members()
@@ -160,6 +164,7 @@
             args[i] = arg
         return args
 
+    @jit.unroll_safe
     def free_arguments(self, args):
         for i in range(len(self.arg_types)):
             conv = self.arg_converters[i]
@@ -294,7 +299,7 @@
 )
 
 
-class W_CPPType(Wrappable):
+class W_CPPScope(Wrappable):
     _immutable_fields_ = ["name", "handle"]
 
     def __init__(self, space, name, handle):
@@ -309,7 +314,7 @@
 
         self.data_members = {}
         # Idem self.methods: a type could hold itself by pointer.
-    
+
     def _find_methods(self):
         num_methods = capi.c_num_methods(self.handle)
         args_temp = {}
@@ -322,6 +327,72 @@
             overload = W_CPPOverload(self.space, name, functions[:])
             self.methods[name] = overload
 
+    def get_method_names(self):
+        return self.space.newlist([self.space.wrap(name) for name in 
self.methods])
+
+    @jit.purefunction
+    def get_overload(self, name):
+        return self.methods[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]
+
+    def invoke(self, name, args_w):
+        overload = self.get_overload(name)
+        return overload.call(NULL_VOIDP, args_w)
+
+W_CPPScope.typedef = TypeDef(
+    'CPPScope',
+    get_method_names = interp2app(W_CPPScope.get_method_names, 
unwrap_spec=['self']),
+    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']),
+)
+
+
+# For now, keep namespaces and classes separate as namespaces are extensible
+# with info from multiple dictionaries and do not need to bother with meta
+# classes for inheritance. Both are python classes, though, and refactoring
+# may be in order at some point.
+class W_CPPNamespace(W_CPPScope):
+
+    def _make_cppfunction(self, method_index):
+        result_type = 
capi.charp2str_free(capi.c_method_result_type(self.handle, method_index))
+        num_args = capi.c_method_num_args(self.handle, method_index)
+        argtypes = []
+        for i in range(num_args):
+            argtype = capi.charp2str_free(capi.c_method_arg_type(self.handle, 
method_index, i))
+        return CPPFunction(self, method_index, result_type, argtypes)
+
+    def _find_data_members(self):
+        num_data_members = capi.c_num_data_members(self.handle)
+        for i in range(num_data_members):
+            data_member_name = 
capi.charp2str_free(capi.c_data_member_name(self.handle, i))
+            cpptype = capi.charp2str_free(capi.c_data_member_type(self.handle, 
i))
+            offset = capi.c_data_member_offset(self.handle, i)
+            data_member = W_CPPStaticDataMember(self.space, cpptype, offset)
+            self.data_members[data_member_name] = data_member
+
+    def is_namespace(self):
+        return self.space.w_True
+
+W_CPPNamespace.typedef = TypeDef(
+    'CPPNamespace',
+    get_method_names = interp2app(W_CPPNamespace.get_method_names, 
unwrap_spec=['self']),
+    get_overload = interp2app(W_CPPNamespace.get_overload, 
unwrap_spec=['self', str]),
+    get_data_member_names = interp2app(W_CPPNamespace.get_data_member_names, 
unwrap_spec=['self']),
+    get_data_member = interp2app(W_CPPNamespace.get_data_member, 
unwrap_spec=['self', str]),
+    is_namespace = interp2app(W_CPPNamespace.is_namespace, 
unwrap_spec=['self']),
+)
+
+
+class W_CPPType(W_CPPScope):
+
     def _make_cppfunction(self, method_index):
         result_type = 
capi.charp2str_free(capi.c_method_result_type(self.handle, method_index))
         num_args = capi.c_method_num_args(self.handle, method_index)
@@ -349,6 +420,9 @@
                 data_member = W_CPPDataMember(self.space, cpptype, offset)
             self.data_members[data_member_name] = data_member
 
+    def is_namespace(self):
+        return self.space.w_False
+
     def get_base_names(self):
         bases = []
         num_bases = capi.c_num_bases(self.handle)
@@ -357,24 +431,6 @@
             bases.append(self.space.wrap(base_name))
         return self.space.newlist(bases)
 
-    def get_method_names(self):
-        return self.space.newlist([self.space.wrap(name) for name in 
self.methods])
-
-    @jit.purefunction
-    def get_overload(self, name):
-        return self.methods[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]
-
-    def invoke(self, name, args_w):
-        overload = self.get_overload(name)
-        return overload.call(NULL_VOIDP, args_w)
-
     def construct(self, args_w):
         overload = self.get_overload(self.name)
         return overload.call(NULL_VOIDP, args_w)
@@ -386,6 +442,7 @@
     get_overload = interp2app(W_CPPType.get_overload, unwrap_spec=['self', 
str]),
     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']),
     construct = interp2app(W_CPPType.construct, unwrap_spec=['self', 
'args_w']),
 )
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
@@ -2,8 +2,15 @@
 import cppyy
 
 
+# For now, keep namespaces and classes separate as namespaces are extensible
+# with info from multiple dictionaries and do not need to bother with meta
+# classes for inheritance. Both are python classes, though, and refactoring
+# may be in order at some point.
+class CppyyNamespace(type):
+    pass
+
 class CppyyClass(type):
-     pass
+    pass
 
 class CppyyObject(object):
     __metaclass__ = CppyyClass
@@ -23,6 +30,7 @@
     return bound_obj
 
 def make_static_function(cpptype, name, rettype):
+    print rettype
     if not rettype:                              # return builtin type
         def method(*args):
             return cpptype.invoke(name, *args)
@@ -45,20 +53,46 @@
     return method
 
 
-_existing_classes = {}
-def get_cppclass(name):
-    # lookup class
+def __ns_getattr__(self, attr):
     try:
-        return _existing_classes[name]
-    except KeyError:
-        pass
+        cppclass = get_cppitem(attr, self.__name__)
+        self.__dict__[attr] = cppclass
+        return cppclass
+    except TypeError, e:
+        import traceback
+        traceback.print_exc()
+        raise AttributeError("namespace object has no attribute '%s'" % attr)
 
-    # if failed, create
 
-    cpptype = cppyy._type_byname(name)
+def make_cppnamespace(name, cppns):
+    d = {}
+
+    # insert static methods into the "namespace" dictionary
+    for f in cppns.get_method_names():
+        cppol = cppns.get_overload(f)
+        d[f] = make_static_function(cppns, f, cppol.get_returntype())
+
+    # create a meta class to allow properties (for static data write access)
+    metans = type(CppyyNamespace)(name+'_meta', (type(type),), {"__getattr__" 
: __ns_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 cppns.get_data_member_names():
+        cppdm = cppns.get_data_member(dm)
+        d[dm] = cppdm
+        setattr(metans, dm, cppdm)
+
+    # create the python-side C++ namespace representation
+    pycppns = metans(name, (type,), d)
+
+    # cache result and return
+    _existing_cppitems[name] = pycppns
+    return pycppns
+
+def make_cppclass(name, cpptype):
     d = {"_cppyyclass" : cpptype}
 
-    # insert (static) methods in the class dictionary
+    # insert (static) methods into the class dictionary
     for f in cpptype.get_method_names():
         cppol = cpptype.get_overload(f)
         if cppol.is_static():
@@ -69,7 +103,7 @@
     # get a list of base classes for class creation
     bases = tuple([get_cppclass(base) for base in cpptype.get_base_names()])
     if not bases:
-         bases = (CppyyObject,)
+        bases = (CppyyObject,)
 
     # create a meta class to allow properties (for static data write access)
     metabases = tuple([type(base) for base in bases])
@@ -88,21 +122,41 @@
     pycpptype = metacpp(name, bases, d)
  
     # cache result and return
-    _existing_classes[name] = pycpptype
+    _existing_cppitems[name] = pycpptype
     return pycpptype
 
-    # TODO: better error reporting
-    # raise TypeError("no such C++ class %s" % name)
 
+_existing_cppitems = {}               # to merge with gbl.__dict__ (?)
+def get_cppitem(name, scope=""):
+    if scope:
+        fullname = scope+"::"+name
+    else:
+        fullname = name
 
-class _gbl(object):
+    # lookup class
+    try:
+        return _existing_cppitems[fullname]
+    except KeyError:
+        pass
+
+    # if failed, create
+
+    cppitem = cppyy._type_byname(fullname)
+    if cppitem.is_namespace():
+        return make_cppnamespace(name, cppitem)
+    else:
+        return make_cppclass(name, cppitem)
+get_cppclass = get_cppitem         # TODO: restrict to classes only (?)
+
+
+class _gbl(object): # TODO: make a CppyyNamespace object
     """Global C++ namespace, i.e. ::."""
 
     def __getattr__(self, attr):
         try:
-            cppclass = get_cppclass(attr)
-            self.__dict__[attr] = cppclass
-            return cppclass
+            cppitem = get_cppitem(attr)
+            self.__dict__[attr] = cppitem
+            return cppitem
         except TypeError, e:
             import traceback
             traceback.print_exc()
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
@@ -6,30 +6,41 @@
 
 
 /* local helpers ---------------------------------------------------------- */
-static inline char* cppstring_to_cstring( const std::string& name ) {
+static inline char* cppstring_to_cstring(const std::string& name) {
     char* name_char = (char*)malloc(name.size() + 1);
     strcpy(name_char, name.c_str());
     return name_char;
 }
 
+static inline Reflex::Scope scope_from_handle(cppyy_typehandle_t handle) {
+    return Reflex::Scope((Reflex::ScopeName*)handle);
+}
+
+static inline Reflex::Type type_from_handle(cppyy_typehandle_t handle) {
+    return Reflex::Scope((Reflex::ScopeName*)handle);
+}
+
 
 /* name to handle --------------------------------------------------------- */
 cppyy_typehandle_t cppyy_get_typehandle(const char* class_name) {
-   return Reflex::Type::ByName(class_name).Id();
+    Reflex::Scope s = Reflex::Scope::ByName(class_name);
+    return Reflex::Scope::ByName(class_name).Id();
 }
 
 
 /* memory management ------------------------------------------------------ */
 void* cppyy_allocate(cppyy_typehandle_t handle) {
-    return Reflex::Type((Reflex::TypeName*)handle).Allocate();
+    Reflex::Type t = type_from_handle(handle);
+    return t.Allocate();
 }
 
 void cppyy_deallocate(cppyy_typehandle_t handle, cppyy_object_t instance) {
-    Reflex::Type((Reflex::TypeName*)handle).Deallocate(instance);
+    Reflex::Type t = type_from_handle(handle);
+    t.Deallocate(instance);
 }
 
 void cppyy_destruct(cppyy_typehandle_t handle, cppyy_object_t self) {
-    Reflex::Type t((Reflex::TypeName*)handle);
+    Reflex::Type t = type_from_handle(handle);
     t.Destruct(self, true);
 }
 
@@ -38,10 +49,10 @@
 void cppyy_call_v(cppyy_typehandle_t handle, int method_index,
                   cppyy_object_t self, int numargs, void* args[]) {
     std::vector<void*> arguments(args, args+numargs);
-    Reflex::Type t((Reflex::TypeName*)handle);
-    Reflex::Member m = t.FunctionMemberAt(method_index);
+    Reflex::Scope s = scope_from_handle(handle);
+    Reflex::Member m = s.FunctionMemberAt(method_index);
     if (self) {
-        Reflex::Object o(t, self);
+        Reflex::Object o((Reflex::Type)s, self);
         m.Invoke(o, 0, arguments);
     } else {
         m.Invoke(0, arguments);
@@ -53,10 +64,10 @@
                              cppyy_object_t self, int numargs, void* args[]) {
     T result;
     std::vector<void*> arguments(args, args+numargs);
-    Reflex::Type t((Reflex::TypeName*)handle);
-    Reflex::Member m = t.FunctionMemberAt(method_index);
+    Reflex::Scope s = scope_from_handle(handle);
+    Reflex::Member m = s.FunctionMemberAt(method_index);
     if (self) {
-        Reflex::Object o(t, self);
+        Reflex::Object o((Reflex::Type)s, self);
         m.Invoke(o, result, arguments);
     } else {
         m.Invoke(result, arguments);
@@ -71,12 +82,12 @@
 
 char cppyy_call_c(cppyy_typehandle_t handle, int method_index,
                  cppyy_object_t self, int numargs, void* args[]) {
-   return cppyy_call_T<char>(handle, method_index, self, numargs, args);
+    return cppyy_call_T<char>(handle, method_index, self, numargs, args);
 }
 
 short cppyy_call_h(cppyy_typehandle_t handle, int method_index,
                    cppyy_object_t self, int numargs, void* args[]) {
-   return cppyy_call_T<short>(handle, method_index, self, numargs, args);
+    return cppyy_call_T<short>(handle, method_index, self, numargs, args);
 }
 
 long cppyy_call_l(cppyy_typehandle_t handle, int method_index,
@@ -96,31 +107,43 @@
 
 
 static cppyy_methptrgetter_t get_methptr_getter(Reflex::Member m) {
-  Reflex::PropertyList plist = m.Properties();
-  if (plist.HasProperty("MethPtrGetter")) {
-    Reflex::Any& value = plist.PropertyValue("MethPtrGetter");
-    return (cppyy_methptrgetter_t)Reflex::any_cast<void*>(value);
-  }
-  else
+    Reflex::PropertyList plist = m.Properties();
+    if (plist.HasProperty("MethPtrGetter")) {
+        Reflex::Any& value = plist.PropertyValue("MethPtrGetter");
+        return (cppyy_methptrgetter_t)Reflex::any_cast<void*>(value);
+    }
     return 0;
 }
 
 cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_typehandle_t handle, int 
method_index)
 {
-    Reflex::Type t((Reflex::TypeName*)handle);
-    Reflex::Member m = t.FunctionMemberAt(method_index);
+    Reflex::Scope s = scope_from_handle(handle);
+    Reflex::Member m = s.FunctionMemberAt(method_index);
     return get_methptr_getter(m);
 }
 
 
+/* scope reflection information ------------------------------------------- */
+int cppyy_is_namespace(cppyy_typehandle_t handle) {
+    Reflex::Scope s = scope_from_handle(handle);
+    return s.IsNamespace();
+}
+
+
 /* type/class reflection information -------------------------------------- */
+char* cppyy_final_name(cppyy_typehandle_t handle) {
+    Reflex::Scope s = scope_from_handle(handle);
+    std::string name = s.Name(Reflex::FINAL);
+    return cppstring_to_cstring(name);
+}
+
 int cppyy_num_bases(cppyy_typehandle_t handle) {
-    Reflex::Type t((Reflex::TypeName*)handle);
+    Reflex::Type t = type_from_handle(handle);
     return t.BaseSize();
 }
 
 char* cppyy_base_name(cppyy_typehandle_t handle, int base_index) {
-    Reflex::Type t((Reflex::TypeName*)handle);
+    Reflex::Type t = type_from_handle(handle);
     Reflex::Base b = t.BaseAt(base_index);
     std::string name = b.Name(Reflex::FINAL|Reflex::SCOPED);
     return cppstring_to_cstring(name);
@@ -129,52 +152,42 @@
 int cppyy_is_subtype(cppyy_typehandle_t h1, cppyy_typehandle_t h2) {
     if (h1 == h2)
         return 1;
-    Reflex::Type t1((Reflex::TypeName*)h1);
-    Reflex::Type t2((Reflex::TypeName*)h2);
+    Reflex::Type t1 = type_from_handle(h1);
+    Reflex::Type t2 = type_from_handle(h2);
     return (int)t2.HasBase(t1);
 }
 
 
 /* method/function reflection information --------------------------------- */
 int cppyy_num_methods(cppyy_typehandle_t handle) {
-    Reflex::Type t((Reflex::TypeName*)handle);
-    // for (int i = 0; i < (int)t.FunctionMemberSize(); i++) {
-    //     Reflex::Member m = t.FunctionMemberAt(i);
-    //     std::cout << i << " " << m.Name() << std::endl;
-    //     std::cout << "    " << "Stubfunction:  " << (void*)m.Stubfunction() 
<< std::endl;
-    //     std::cout << "    " << "MethPtrGetter: " << 
(void*)get_methptr_getter(m) << std::endl;
-    //     for (int j = 0; j < (int)m.FunctionParameterSize(); j++) {
-    //         Reflex::Type at = m.TypeOf().FunctionParameterAt(j);
-    //         std::cout << "    " << j << " " << at.Name() << std::endl;
-    //     }
-    // }
-    return t.FunctionMemberSize();
+    Reflex::Scope s = scope_from_handle(handle);
+    return s.FunctionMemberSize();
 }
 
 char* cppyy_method_name(cppyy_typehandle_t handle, int method_index) {
-    Reflex::Type t((Reflex::TypeName*)handle);
-    Reflex::Member m = t.FunctionMemberAt(method_index);
+    Reflex::Scope s = scope_from_handle(handle);
+    Reflex::Member m = s.FunctionMemberAt(method_index);
     std::string name = m.Name();
     return cppstring_to_cstring(name);
 }
 
 char* cppyy_method_result_type(cppyy_typehandle_t handle, int method_index) {
-    Reflex::Type t((Reflex::TypeName*)handle);
-    Reflex::Member m = t.FunctionMemberAt(method_index);
+    Reflex::Scope s = scope_from_handle(handle);
+    Reflex::Member m = s.FunctionMemberAt(method_index);
     Reflex::Type rt = m.TypeOf().ReturnType();
     std::string name = rt.Name(Reflex::FINAL|Reflex::SCOPED|Reflex::QUALIFIED);
     return cppstring_to_cstring(name);
 }
 
 int cppyy_method_num_args(cppyy_typehandle_t handle, int method_index) {
-    Reflex::Type t((Reflex::TypeName*)handle);
-    Reflex::Member m = t.FunctionMemberAt(method_index);
+    Reflex::Scope s = scope_from_handle(handle);
+    Reflex::Member m = s.FunctionMemberAt(method_index);
     return m.FunctionParameterSize();
 }
 
 char* cppyy_method_arg_type(cppyy_typehandle_t handle, int method_index, int 
arg_index) {
-    Reflex::Type t((Reflex::TypeName*)handle);
-    Reflex::Member m = t.FunctionMemberAt(method_index);
+    Reflex::Scope s = scope_from_handle(handle);
+    Reflex::Member m = s.FunctionMemberAt(method_index);
     Reflex::Type at = m.TypeOf().FunctionParameterAt(arg_index);
     std::string name = at.Name(Reflex::FINAL|Reflex::SCOPED|Reflex::QUALIFIED);
     return cppstring_to_cstring(name);
@@ -182,52 +195,48 @@
 
 
 int cppyy_is_constructor(cppyy_typehandle_t handle, int method_index) {
-    Reflex::Type t((Reflex::TypeName*)handle);
-    Reflex::Member m = t.FunctionMemberAt(method_index);
+    Reflex::Scope s = scope_from_handle(handle);
+    Reflex::Member m = s.FunctionMemberAt(method_index);
     return m.IsConstructor();
 }
 
 int cppyy_is_staticmethod(cppyy_typehandle_t handle, int method_index) {
-    Reflex::Type t((Reflex::TypeName*)handle);
-    Reflex::Member m = t.FunctionMemberAt(method_index);
+    Reflex::Scope s = scope_from_handle(handle);
+    Reflex::Member m = s.FunctionMemberAt(method_index);
     return m.IsStatic();
 }
 
 
 /* data member reflection information ------------------------------------- */
 int cppyy_num_data_members(cppyy_typehandle_t handle) {
-    Reflex::Type t((Reflex::TypeName*)handle);
-    return t.DataMemberSize();
+    Reflex::Scope s = scope_from_handle(handle);
+    return s.DataMemberSize();
 }
 
 char* cppyy_data_member_name(cppyy_typehandle_t handle, int data_member_index) 
{
-    Reflex::Type t((Reflex::TypeName*)handle);
-    Reflex::Member m = t.DataMemberAt(data_member_index);
+    Reflex::Scope s = scope_from_handle(handle);
+    Reflex::Member m = s.DataMemberAt(data_member_index);
     std::string name = m.Name();
-    char* name_char = (char*)malloc(name.size() + 1);
-    strcpy(name_char, name.c_str());
-    return name_char;
+    return cppstring_to_cstring(name);
 }
 
 char* cppyy_data_member_type(cppyy_typehandle_t handle, int data_member_index) 
{
-    Reflex::Type t((Reflex::TypeName*)handle);
-    Reflex::Member m = t.DataMemberAt(data_member_index);
+    Reflex::Scope s = scope_from_handle(handle);
+    Reflex::Member m = s.DataMemberAt(data_member_index);
     std::string name = 
m.TypeOf().Name(Reflex::FINAL|Reflex::SCOPED|Reflex::QUALIFIED);
-    char* name_char = (char*)malloc(name.size() + 1);
-    strcpy(name_char, name.c_str());
-    return name_char;
+    return cppstring_to_cstring(name);
 }
 
 size_t cppyy_data_member_offset(cppyy_typehandle_t handle, int 
data_member_index) {
-    Reflex::Type t((Reflex::TypeName*)handle);
-    Reflex::Member m = t.DataMemberAt(data_member_index);
+    Reflex::Scope s = scope_from_handle(handle);
+    Reflex::Member m = s.DataMemberAt(data_member_index);
     return m.Offset();
 }
 
 
 int cppyy_is_staticdata(cppyy_typehandle_t handle, int data_member_index) {
-    Reflex::Type t((Reflex::TypeName*)handle);
-    Reflex::Member m = t.DataMemberAt(data_member_index);
+    Reflex::Scope s = scope_from_handle(handle);
+    Reflex::Member m = s.DataMemberAt(data_member_index);
     return m.IsStatic();
 }
 
diff --git a/pypy/module/cppyy/test/advancedcpp.cxx 
b/pypy/module/cppyy/test/advancedcpp.cxx
--- a/pypy/module/cppyy/test/advancedcpp.cxx
+++ b/pypy/module/cppyy/test/advancedcpp.cxx
@@ -8,6 +8,15 @@
 int get_d( d_class& d ) { return d.m_d; }
 
 
+// for namespace testing
+int a_ns::g_a                         = 11;
+int a_ns::b_class::s_b                = 22;
+int a_ns::b_class::c_class::s_c       = 33;
+int a_ns::d_ns::g_d                   = 44;
+int a_ns::d_ns::e_class::s_e          = 55;
+int a_ns::d_ns::e_class::f_class::s_f = 66;
+
+
 // helpers for checking pass-by-ref
 void set_int_through_ref(int& i, int val)             { i = val; }
 int pass_int_through_const_ref(const int& i)          { return i; }
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
@@ -82,6 +82,42 @@
 
 
 //===========================================================================
+namespace a_ns {                   // for namespace testing
+   extern int g_a;
+
+   struct b_class {
+      b_class() { m_b = -2; }
+      int m_b;
+      static int s_b;
+
+      struct c_class {
+         c_class() { m_c = -3; }
+         int m_c;
+         static int s_c;
+      };
+   };
+
+   namespace d_ns {
+      extern int g_d;
+
+      struct e_class {
+         e_class() { m_e = -5; }
+         int m_e;
+         static int s_e;
+
+         struct f_class {
+            f_class() { m_f = -6; }
+            int m_f;
+            static int s_f;
+         };
+      };
+
+   } // namespace d_ns
+
+} // namespace a_ns
+
+
+//===========================================================================
 template< typename T >             // for template testing
 class T1 {
 public:
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
@@ -23,7 +23,7 @@
             import cppyy
             return cppyy.load_lib(%r)""" % (shared_lib, ))
 
-    def test1_simple_inheritence(self):
+    def test01_simple_inheritence(self):
         """Test binding of a basic inheritance structure"""
 
         import cppyy
@@ -38,3 +38,22 @@
         assert isinstance( c, base_class )
 
         c.destruct()
+
+    def test02_namespaces(self):
+        """Test access to namespaces and inner classes"""
+
+        import cppyy
+
+#        assert cppyy.gbl.a_ns.g_a                           == 11
+        assert cppyy.gbl.a_ns.b_class.s_b                   == 22
+        assert cppyy.gbl.a_ns.b_class().m_b                 == -2
+#        assert cppyy.gbl.a_ns.b_class.c_class.s_c           == 33
+#        assert cppyy.gbl.a_ns.b_class.c_class().m_c         == -3
+#        assert cppyy.gbl.a_ns.d_ns.g_d                      == 44
+#        assert cppyy.gbl.a_ns.d_ns.e_class.s_e              == 55
+#        assert cppyy.gbl.a_ns.d_ns.e_class().m_e            == -5
+#        assert cppyy.gbl.a_ns.d_ns.e_class.f_class.s_f      == 66
+#        assert cppyy.gbl.a_ns.d_ns.e_class.f_class().m_f    == -6
+
+        assert cppyy.gbl.a_ns      is cppyy.gbl.a_ns
+        assert cppyy.gbl.a_ns.d_ns is cppyy.gbl.a_ns.d_ns
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to