diff --git a/Cython/Compiler/Nodes.py b/Cython/Compiler/Nodes.py
index 326fe528deb9aa975892ff69cd28deec0f274c15..1f8465a82c971edb1efccbff4937c81d881d1a3c 100644
--- a/Cython/Compiler/Nodes.py
+++ b/Cython/Compiler/Nodes.py
@@ -1635,52 +1635,85 @@ class CppClassNode(CStructOrUnionDefNode, BlockNode):
                         self.cyp_wrapper.body.stats.append(py_method_wrapper)
 
     def synthesize_cypclass_method_wrapper(self, cfunc_method):
-        from .CypclassWrapper import underlying_name, cycplass_special_entry_names
-
+        
         if cfunc_method.is_static_method:
             return # for now skip static methods
+        
+        # C++ methods have an implict 'this', so the 'self' argument is skipped in the declarator
+        skipped_self = cfunc_method.cfunc_declarator.skipped_self
+        if not skipped_self:
+            return # if this ever happens (?), skip non-static methods without a self argument
+
+        from .CypclassWrapper import underlying_name, cycplass_special_entry_names
+        from . import ExprNodes
 
         cfunc_declarator = cfunc_method.cfunc_declarator
-        py_name = cfunc_method.entry.name
-        
-        # transform e.g. <init> back into __init__
+
+        # > name of the wrapping method: same name
+        cfunc_name = cfunc_method.entry.name
+        py_name = cfunc_name
         try:
+            # transform e.g. <init> back into __init__
             py_name = cycplass_special_entry_names[py_name]
         except KeyError:
+            # no need to transform this name
             pass
-        
-        py_args = [arg.clone_node() for arg in cfunc_declarator.args]
 
-        py_doc = cfunc_method.doc
+        # > self argument of the wrapper method: same name, but type of the wrapper cclass
+        self_name, self_type, self_pos, self_arg = skipped_self
+        py_self_arg = CArgDeclNode(
+            self_pos,
+            base_type = CSimpleBaseTypeNode(
+                self_pos,
+                name = self.cyp_wrapper.class_name,
+                module_path = [],
+                signed = 1,
+                is_basic_c_type = 0,
+                longness = 0,
+                is_self_arg = 0, # only true for C methods
+                templates = None
+            ),
+            declarator = CNameDeclaratorNode(self_pos, name=self_name, cname=None),
+            not_none = 0,
+            or_none = 0,
+            default = None,
+            annotation = None,
+            kw_only = 0
+        )
 
-        arg_names = [arg.name for arg in py_args]
+        # > all arguments of the wrapper method declaration
+        py_args = [py_self_arg]
+        for arg in cfunc_declarator.args:
+            py_args.append(arg.clone_node())
 
-        # C++ methods have an implict 'this', so the 'self' argument is skipped in the declarator
-        skipped_self = cfunc_method.cfunc_declarator.skipped_self
-        if not skipped_self:
-            return # if this ever happens (?), skip non-static methods without a self argument
-        
-        from . import ExprNodes
+        # > same docstring
+        py_doc = cfunc_method.doc
+
+        # > names of the arguments passed when calling the underlying method; self not included
+        arg_objs = [ExprNodes.NameNode(arg.pos, name=arg.name) for arg in cfunc_declarator.args]
 
-        # self_name, self_type, self_pos, self_arg = skipped_self
-        type_entry = self.cyp_wrapper.entry
-        type_arg = ExprNodes.NameNode(self.pos, name=type_entry.name)
-        type_arg.entry = type_entry
+        # > reference to the self argument of the wrapper method
+        self_obj = ExprNodes.NameNode(self_pos, name=self_name)
 
-        cfunc = ExprNodes.AttributeNode(cfunc_method.pos, obj=type_arg, attribute=underlying_name)
+        # > access the method of the underlying cyobject from the self argument of the wrapper method
+        underlying_obj = ExprNodes.AttributeNode(cfunc_method.pos, obj=self_obj, attribute=underlying_name)
+        cfunc = ExprNodes.AttributeNode(cfunc_method.pos, obj=underlying_obj, attribute=cfunc_name)
 
+        # > call to the underlying method
         c_call = ExprNodes.SimpleCallNode(
             cfunc_method.pos,
             function=cfunc,
-            args=[ExprNodes.NameNode(cfunc_method.pos, name=n) for n in arg_names]
+            args=arg_objs
         )
 
+        # > return the result of the call if the underlying return type is not void
         if cfunc_method.type.return_type.is_void:
             py_stat = ExprStatNode(pos=cfunc_method.pos, expr=c_call)
         else:
             py_stat = ReturnStatNode(pos=cfunc_method.pos, return_type=PyrexTypes.py_object_type, value=c_call)
         py_body = StatListNode(cfunc_method.pos, stats=[py_stat])
 
+        # > the wrapper method
         return DefNode(
             cfunc_method.pos,
             name = py_name,