[pypy-commit] pypy reflex-support: offsets for calling base classes
wlav
noreply at buildbot.pypy.org
Fri Jul 1 01:15:55 CEST 2011
Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r45201:e58b8f224098
Date: 2011-06-30 13:20 -0700
http://bitbucket.org/pypy/pypy/changeset/e58b8f224098/
Log: offsets for calling base classes
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
@@ -78,6 +78,10 @@
"cppyy_is_subtype",
[C_TYPEHANDLE, C_TYPEHANDLE], rffi.INT,
compilation_info=eci)
+c_base_offset = rffi.llexternal(
+ "cppyy_base_offset",
+ [C_TYPEHANDLE, C_TYPEHANDLE], rffi.SIZE_T,
+ compilation_info=eci)
c_call_v = rffi.llexternal(
@@ -168,7 +172,7 @@
compilation_info=eci)
c_data_member_offset = rffi.llexternal(
"cppyy_data_member_offset",
- [C_TYPEHANDLE, rffi.INT], rffi.INT,
+ [C_TYPEHANDLE, rffi.INT], rffi.SIZE_T,
compilation_info=eci)
c_is_staticdata = rffi.llexternal(
diff --git a/pypy/module/cppyy/converter.py b/pypy/module/cppyy/converter.py
--- a/pypy/module/cppyy/converter.py
+++ b/pypy/module/cppyy/converter.py
@@ -357,7 +357,10 @@
obj = space.interpclass_w(w_obj)
if isinstance(obj, W_CPPInstance):
if capi.c_is_subtype(obj.cppclass.handle, self.cpptype.handle):
- return obj.rawobject
+ offset = capi.c_base_offset(obj.cppclass.handle, self.cpptype.handle)
+ obj_address = lltype.direct_ptradd(obj.rawobject, offset)
+ objptr = rffi.cast(rffi.CCHARP, obj_address)
+ return objptr
raise OperationError(space.w_TypeError,
space.wrap("cannot pass %s as %s" % (
space.type(w_obj).getname(space, "?"),
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
@@ -36,7 +36,8 @@
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);
+ int cppyy_is_subtype(cppyy_typehandle_t dh, cppyy_typehandle_t bh);
+ size_t cppyy_base_offset(cppyy_typehandle_t dh, cppyy_typehandle_t bh);
/* method/function reflection information */
int cppyy_num_methods(cppyy_typehandle_t handle);
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
@@ -21,6 +21,36 @@
return Reflex::Scope((Reflex::ScopeName*)handle);
}
+static inline size_t base_offset(const Reflex::Type& td, const Reflex::Type& tb) {
+ // when dealing with virtual inheritance the only (reasonably) well-defined info is
+ // in a Reflex internal base table, that contains all offsets within the hierarchy
+ Reflex::Member getbases = td.FunctionMemberByName(
+ "__getBasesTable", Reflex::Type(), 0, Reflex::INHERITEDMEMBERS_NO, Reflex::DELAYEDLOAD_OFF);
+ if (getbases) {
+ typedef std::vector<std::pair<Reflex::Base, int> > Bases_t;
+ Bases_t* bases;
+ Reflex::Object bases_holder(Reflex::Type::ByTypeInfo(typeid(Bases_t)), &bases);
+ getbases.Invoke(&bases_holder);
+
+ for (Bases_t::iterator ibase = bases->begin(); ibase != bases->end(); ++ibase) {
+ if (ibase->first.ToType() == tb) {
+ if (ibase->first.IsVirtual()) {
+ Reflex::Object o = td.Construct();
+ size_t offset = ibase->first.Offset(o.Address());
+ o.Destruct();
+ return offset;
+ } else
+ return ibase->first.Offset(0);
+ }
+ }
+
+ // contrary to typical invoke()s, the result of the internal getbases function
+ // is a pointer to a function static, so no delete
+ }
+
+ return 0;
+}
+
/* name to handle --------------------------------------------------------- */
cppyy_typehandle_t cppyy_get_typehandle(const char* class_name) {
@@ -171,12 +201,20 @@
return cppstring_to_cstring(name);
}
-int cppyy_is_subtype(cppyy_typehandle_t h1, cppyy_typehandle_t h2) {
- if (h1 == h2)
+int cppyy_is_subtype(cppyy_typehandle_t dh, cppyy_typehandle_t bh) {
+ if (dh == bh)
return 1;
- Reflex::Type t1 = type_from_handle(h1);
- Reflex::Type t2 = type_from_handle(h2);
- return (int)t2.HasBase(t1);
+ Reflex::Type td = type_from_handle(dh);
+ Reflex::Type tb = type_from_handle(bh);
+ return (int)td.HasBase(tb);
+}
+
+size_t cppyy_base_offset(cppyy_typehandle_t dh, cppyy_typehandle_t bh) {
+ if (dh == bh)
+ return 0;
+ Reflex::Type td = type_from_handle(dh);
+ Reflex::Type tb = type_from_handle(bh);
+ return base_offset(td, tb);
}
@@ -265,34 +303,8 @@
if (s != m.DeclaringScope()) {
// in case this data member is part of a base class, the offset is complicated
- // when dealing with virtual inheritance and only (reasonably) well-defined with a
- // Reflex internal base table, that contains all offsets within the full hierarchy
- Reflex::Member getbases = s.FunctionMemberByName(
- "__getBasesTable", Reflex::Type(), 0, Reflex::INHERITEDMEMBERS_NO, Reflex::DELAYEDLOAD_OFF);
- if (getbases) {
- typedef std::vector<std::pair<Reflex::Base, int> > Bases_t;
- Bases_t* bases;
- Reflex::Object bases_holder(Reflex::Type::ByTypeInfo(typeid(Bases_t)), &bases);
- getbases.Invoke(&bases_holder);
-
- Reflex::Type d = m.DeclaringType();
-
- for (Bases_t::iterator ibase = bases->begin(); ibase != bases->end(); ++ibase) {
- if (ibase->first.ToType() == d) {
- if (d.IsVirtual()) {
- Reflex::Type t = type_from_handle(handle);
- Reflex::Object o = t.Construct();
- size_t offset = ibase->first.Offset(o.Address()) + m.Offset();
- o.Destruct();
- return offset;
- } else
- return ibase->first.Offset(0);
- }
- }
-
- // contrary to typical invoke()s, the result of the internal getbases function
- // is a pointer to a function static, so no delete
- }
+ // when dealing with virtual inheritance and needs to be calculated
+ return base_offset(s, m.DeclaringType()) + m.Offset();
}
return m.Offset();
diff --git a/pypy/module/cppyy/test/advancedcpp.xml b/pypy/module/cppyy/test/advancedcpp.xml
--- a/pypy/module/cppyy/test/advancedcpp.xml
+++ b/pypy/module/cppyy/test/advancedcpp.xml
@@ -12,6 +12,8 @@
<class name="c_class_2" />
<class name="d_class" />
+ <function pattern="get_*" />
+
<class pattern="T1<*>" />
<class pattern="T2<*>" />
<class pattern="T3<*>" />
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 test01_default_argeumetns(self):
+ def test01_default_arguments(self):
"""Test usage of default arguments"""
import cppyy
@@ -277,3 +277,36 @@
# assert d.get_value() == 44
d.destruct()
+
+ def test07_pass_by_reference(self):
+ """Test reference passing when using virtual inheritance"""
+
+ import cppyy
+ gbl = cppyy.gbl
+ b_class = gbl.b_class
+ c_class = gbl.c_class_2
+ d_class = gbl.d_class
+
+ #-----
+ b = b_class()
+ b.m_a, b.m_b = 11, 22
+ assert gbl.get_a(b) == 11
+ assert gbl.get_b(b) == 22
+ b.destruct()
+
+ #-----
+ c = c_class()
+ c.m_a, c.m_b, c.m_c = 11, 22, 33
+ assert gbl.get_a(c) == 11
+ assert gbl.get_b(c) == 22
+ assert gbl.get_c(c) == 33
+ c.destruct()
+
+ #-----
+ d = d_class()
+ d.m_a, d.m_b, d.m_c, d.m_d = 11, 22, 33, 44
+ assert gbl.get_a(d) == 11
+ assert gbl.get_b(d) == 22
+ assert gbl.get_c(d) == 33
+ assert gbl.get_d(d) == 44
+ d.destruct()
More information about the pypy-commit
mailing list