Author: Wim Lavrijsen <[email protected]>
Branch: reflex-support
Changeset: r44293:eee51741c1c1
Date: 2011-05-18 14:38 -0700
http://bitbucket.org/pypy/pypy/changeset/eee51741c1c1/

Log:    initial base class support

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
@@ -42,6 +42,28 @@
     [C_TYPEHANDLE, C_OBJECT], lltype.Void,
     compilation_info=eci)
 
+c_destruct = rffi.llexternal(
+    "cppyy_destruct",
+    [C_TYPEHANDLE, C_OBJECT], lltype.Void,
+    compilation_info=eci)
+
+
+c_num_bases = rffi.llexternal(
+    "cppyy_num_bases",
+    [C_TYPEHANDLE], rffi.INT,
+    compilation_info=eci)
+
+c_base_name = rffi.llexternal(
+    "cppyy_base_name",
+    [C_TYPEHANDLE, rffi.INT], rffi.CCHARP,
+    compilation_info=eci)
+
+c_is_subtype = rffi.llexternal(
+    "cppyy_is_subtype",
+    [C_TYPEHANDLE, C_TYPEHANDLE], rffi.INT,
+    compilation_info=eci)
+
+
 c_call_v = rffi.llexternal(
     "cppyy_call_v",
     [C_TYPEHANDLE, rffi.INT, C_OBJECT, rffi.INT, rffi.VOIDPP], lltype.Void,
@@ -71,20 +93,12 @@
     [C_TYPEHANDLE, rffi.INT, C_OBJECT, rffi.INT, rffi.VOIDPP], rffi.DOUBLE,
     compilation_info=eci)
 
-c_destruct = rffi.llexternal(
-    "cppyy_destruct",
-    [C_TYPEHANDLE, C_OBJECT], lltype.Void,
-    compilation_info=eci)
 
 c_get_methptr_getter = rffi.llexternal(
     "cppyy_get_methptr_getter",
     [C_TYPEHANDLE, rffi.INT], C_METHPTRGETTER_PTR,
     compilation_info=eci)
 
-c_is_subtype = rffi.llexternal(
-    "cppyy_is_subtype",
-    [C_TYPEHANDLE, C_TYPEHANDLE], rffi.INT,
-    compilation_info=eci)
 
 c_num_methods = rffi.llexternal(
     "cppyy_num_methods",
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
@@ -2,6 +2,7 @@
 #define CPPYY_CPPYY
 
 #include "Reflex/Type.h"
+#include "Reflex/Base.h"
 #include "Reflex/Member.h"
 #include "Reflex/Object.h"
 #include "Reflex/Builder/TypeBuilder.h"
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
@@ -9,10 +9,13 @@
     typedef void* cppyy_object_t;
     typedef void* (*cppyy_methptrgetter_t)(cppyy_object_t);
 
+    /* name to handle */
     cppyy_typehandle_t cppyy_get_typehandle(const char* class_name);
 
+    /* memory management */
     void* cppyy_allocate(cppyy_typehandle_t handle);
     void cppyy_deallocate(cppyy_typehandle_t handle, cppyy_object_t instance);
+    void cppyy_destruct(cppyy_typehandle_t handle, cppyy_object_t self);
 
     /* method/function dispatching */
     void   cppyy_call_v(cppyy_typehandle_t handle, int method_index, 
cppyy_object_t self, int numargs, void* args[]);
@@ -23,10 +26,11 @@
     double cppyy_call_f(cppyy_typehandle_t handle, int method_index, 
cppyy_object_t self, int numargs, void* args[]);
     double cppyy_call_d(cppyy_typehandle_t handle, int method_index, 
cppyy_object_t self, int numargs, void* args[]);
 
-    void cppyy_destruct(cppyy_typehandle_t handle, cppyy_object_t self);
     cppyy_methptrgetter_t cppyy_get_methptr_getter(cppyy_typehandle_t handle, 
int method_index);
 
-    /* type properties */
+    /* type/class reflection information 
-------------------------------------- */
+    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);
 
     /* method/function reflection information */
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
@@ -338,6 +338,14 @@
                 data_member = W_CPPDataMember(self.space, cpptype, offset)
             self.data_members[data_member_name] = data_member
 
+    def get_base_names(self):
+        bases = []
+        num_bases = capi.c_num_bases(self.handle)
+        for i in range(num_bases):
+            base_name = capi.charp2str_free(capi.c_base_name(self.handle, i))
+            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])
 
@@ -362,6 +370,7 @@
 
 W_CPPType.typedef = TypeDef(
     'CPPType',
+    get_base_names = interp2app(W_CPPType.get_base_names, 
unwrap_spec=['self']),
     get_method_names = interp2app(W_CPPType.get_method_names, 
unwrap_spec=['self']),
     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']),
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
@@ -6,12 +6,15 @@
      pass
 
 class CppyyObject(object):
+    __metaclass__ = CppyyClass
+
     def __init__(self, *args):
         self._cppinstance = self._cppyyclass.construct(*args)
         
     def destruct(self):
         self._cppinstance.destruct()
 
+
 def bind_object(cppobj, cppclass):
     if cppobj is None:
         return None
@@ -52,7 +55,6 @@
 
     # if failed, create
 
-    # TODO: handle base classes through lookup
     cpptype = cppyy._type_byname(name)
     d = {"_cppyyclass" : cpptype}
 
@@ -64,8 +66,14 @@
         else:
             d[f] = make_method(f, cppol.get_returntype())
 
+    # 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,)
+
     # create a meta class to allow properties (for static data write access)
-    metacpp = type(CppyyClass)(name+'_meta', (type,), {})
+    metabases = tuple([type(base) for base in bases])
+    metacpp = type(CppyyClass)(name+'_meta', metabases, {})
 
     # 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)
@@ -77,7 +85,10 @@
             setattr(metacpp, dm, cppdm)
 
     # create the python-side C++ class representation
-    pycpptype = metacpp(name, (CppyyObject,), d)
+    pycpptype = metacpp(name, bases, d)
+ 
+    # cache result and return
+    _existing_classes[name] = pycpptype
     return pycpptype
 
     # TODO: better error reporting
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
@@ -1,14 +1,25 @@
 #include "cppyy.h"
 #include "reflexcwrapper.h"
+#include <iostream>
+#include <string>
 #include <vector>
-#include <iostream>
 
 
+/* local helpers ---------------------------------------------------------- */
+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;
+}
+
+
+/* name to handle --------------------------------------------------------- */
 cppyy_typehandle_t cppyy_get_typehandle(const char* class_name) {
    return Reflex::Type::ByName(class_name).Id();
 }
 
 
+/* memory management ------------------------------------------------------ */
 void* cppyy_allocate(cppyy_typehandle_t handle) {
     return Reflex::Type((Reflex::TypeName*)handle).Allocate();
 }
@@ -17,6 +28,11 @@
     Reflex::Type((Reflex::TypeName*)handle).Deallocate(instance);
 }
 
+void cppyy_destruct(cppyy_typehandle_t handle, cppyy_object_t self) {
+    Reflex::Type t((Reflex::TypeName*)handle);
+    t.Destruct(self, true);
+}
+
 
 /* method/function dispatching -------------------------------------------- */
 void cppyy_call_v(cppyy_typehandle_t handle, int method_index,
@@ -78,11 +94,6 @@
     return cppyy_call_T<double>(handle, method_index, self, numargs, args);
 }   
 
-void cppyy_destruct(cppyy_typehandle_t handle, cppyy_object_t self) {
-    Reflex::Type t((Reflex::TypeName*)handle);
-    t.Destruct(self, true);
-}
-
 
 static cppyy_methptrgetter_t get_methptr_getter(Reflex::Member m) {
   Reflex::PropertyList plist = m.Properties();
@@ -103,6 +114,18 @@
 
 
 /* type/class reflection information -------------------------------------- */
+int cppyy_num_bases(cppyy_typehandle_t handle) {
+    Reflex::Type t((Reflex::TypeName*)handle);
+    return t.BaseSize();
+}
+
+char* cppyy_base_name(cppyy_typehandle_t handle, int base_index) {
+    Reflex::Type t((Reflex::TypeName*)handle);
+    Reflex::Base b = t.BaseAt(base_index);
+    std::string name = b.Name(Reflex::FINAL|Reflex::SCOPED);
+    return cppstring_to_cstring(name);
+}
+
 int cppyy_is_subtype(cppyy_typehandle_t h1, cppyy_typehandle_t h2) {
     if (h1 == h2)
         return 1;
@@ -132,9 +155,7 @@
     Reflex::Type t((Reflex::TypeName*)handle);
     Reflex::Member m = t.FunctionMemberAt(method_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_method_result_type(cppyy_typehandle_t handle, int method_index) {
@@ -142,9 +163,7 @@
     Reflex::Member m = t.FunctionMemberAt(method_index);
     Reflex::Type rt = m.TypeOf().ReturnType();
     std::string name = rt.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);
 }
 
 int cppyy_method_num_args(cppyy_typehandle_t handle, int method_index) {
@@ -158,9 +177,7 @@
     Reflex::Member m = t.FunctionMemberAt(method_index);
     Reflex::Type at = m.TypeOf().FunctionParameterAt(arg_index);
     std::string name = at.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);
 }
 
 
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
@@ -26,4 +26,15 @@
     def test1_simple_inheritence(self):
         """Test binding of a basic inheritance structure"""
 
-        pass
+        import cppyy
+        base_class    = cppyy.gbl.base_class
+        derived_class = cppyy.gbl.derived_class
+
+        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 )
+
+        c.destruct()
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to