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