[pypy-commit] pypy reflex-support: fix for issue 1676

wlav noreply at buildbot.pypy.org
Sat Apr 26 02:10:59 CEST 2014


Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r70989:866f101100fc
Date: 2014-04-25 16:23 -0700
http://bitbucket.org/pypy/pypy/changeset/866f101100fc/

Log:	fix for issue 1676

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
@@ -450,8 +450,8 @@
 
 class CPPConstructor(CPPMethod):
     """Method dispatcher that constructs new objects. This method can not have
-    a fast path, a the allocation of the object is currently left to the
-    reflection layer only, b/c the C++ class may have an overloaded operator
+    a fast path, as the allocation of the object is currently left to the
+    reflection layer only, since the C++ class may have an overloaded operator
     new, disallowing malloc here."""
 
     _immutable_ = True
@@ -460,8 +460,18 @@
         # TODO: these casts are very, very un-pretty; need to find a way of
         # re-using CPPMethod's features w/o these roundabouts
         vscope = rffi.cast(capi.C_OBJECT, self.scope.handle)
-        w_result = CPPMethod.call(self, vscope, args_w)
+        cppinstance = None
+        try:
+            cppinstance = self.space.interp_w(W_CPPInstance, args_w[0], can_be_None=False)
+            use_args_w = args_w[1:]
+        except (OperationError, TypeError), e:
+            use_args_w = args_w
+        w_result = CPPMethod.call(self, vscope, use_args_w)
         newthis = rffi.cast(capi.C_OBJECT, self.space.int_w(w_result))
+        if cppinstance:
+            cppinstance._rawobject = newthis
+            memory_regulator.register(cppinstance)
+            return args_w[0]
         return wrap_cppobject(self.space, newthis, self.scope,
                               do_cast=False, python_owns=True, fresh=True)
 
@@ -1141,10 +1151,14 @@
         self.objects = rweakref.RWeakValueDictionary(int, W_CPPInstance)
 
     def register(self, obj):
+        if not obj._rawobject:
+            return
         int_address = int(rffi.cast(rffi.LONG, obj._rawobject))
         self.objects.set(int_address, obj)
 
     def unregister(self, obj):
+        if not obj._rawobject:
+            return
         int_address = int(rffi.cast(rffi.LONG, obj._rawobject))
         self.objects.set(int_address, None)
 
@@ -1194,7 +1208,7 @@
         w_pycppclass = get_pythonized_cppclass(space, cppclass.handle)
 
     # try to recycle existing object if this one is not newly created
-    if not fresh:
+    if not fresh and rawobject:
         obj = memory_regulator.retrieve(rawobject)
         if obj is not None and obj.cppclass is cppclass:
             return obj
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
@@ -146,7 +146,12 @@
             raise TypeError(msg)
     else:
         def __new__(cls, *args):
-            return constructor_overload.call(None, *args)
+            # create a place-holder only as there may be a derived class defined
+            import cppyy
+            instance = cppyy.bind_object(0, class_name, True)
+            if not instance.__class__ is cls:
+                instance.__class__ = cls     # happens for derived class
+            return instance
     return __new__
 
 def make_pycppclass(scope, class_name, final_class_name, cppclass):
@@ -427,7 +432,9 @@
         __metaclass__ = CppyyClassMeta
 
         def __init__(self, *args, **kwds):
-            pass   # ignored, for the C++ backend, ctor == __new__ + __init__
+            # self is only a placeholder; now create the actual C++ object
+            args = (self,) + args
+            self._cpp_proxy.get_overload(self._cpp_proxy.type_name).call(None, *args)
 
     # class generator callback
     cppyy._set_class_generator(clgen_callback)
diff --git a/pypy/module/cppyy/test/test_pythonify.py b/pypy/module/cppyy/test/test_pythonify.py
--- a/pypy/module/cppyy/test/test_pythonify.py
+++ b/pypy/module/cppyy/test/test_pythonify.py
@@ -332,6 +332,33 @@
        assert 2 == e.fresh(1)
        assert 3 == e.fresh(2)
 
+    def test16_subclassing(self):
+        """A sub-class on the python side should have that class as type"""
+
+        import cppyy
+        example01 = cppyy.gbl.example01
+
+        o = example01()
+        assert type(o) == example01
+
+        class MyClass1(example01):
+            def myfunc(self):
+                return 1
+
+        o = MyClass1()
+        assert type(o) == MyClass1
+        assert isinstance(o, example01)
+        assert o.myfunc() == 1
+
+        class MyClass2(example01):
+            def __init__(self, what):
+                example01.__init__(self)
+                self.what = what
+
+        o = MyClass2('hi')
+        assert type(o) == MyClass2
+        assert o.what == 'hi'
+
 
 class AppTestPYTHONIFY_UI:
     spaceconfig = dict(usemodules=['cppyy', '_rawffi', 'itertools'])


More information about the pypy-commit mailing list