[C++-sig] rfe: change of behaviour with return_internal_reference policy

gideon may gideon at computer.org
Mon Aug 19 15:10:37 CEST 2002


Dear Dave,

I have the following code example (obvious stuff missing :
<============================================
class Node {
};

class Leaf1 : public Node {
};

class Leaf2 : public Node {
};

class Group : public Node {
  public:
    void addChild(Node * child) { _child = child; }
    Node * getChild() { return _child; }
  private:
    Node * _child;
};

toGroup(Node * self) {    return dynamic_cast<Group *>(self); }

toLeaf1(Node * self) {    return dynamic_cast<Leaf1 *>(self); }

toLeaf2(Node * self) {    return dynamic_cast<Leaf2 *>(self); }

BOOST_PYTHON_MODULE_INIT(cast)
{
    module("cast")
        .add(class_<Node>("Node")
            .def_init()
            .def("toGroup", &nodeToGroup, return_internal_reference<>())
            .def("toLeaf1", &nodeToLeaf1, return_internal_reference<>())
            .def("toLeaf2", &nodeToLeaf2, return_internal_reference<>())
         )
         .add(class_<Group>("Group")
         .add(class_<Leaf1>("Leaf1")
         .add(class_<Leaf2>("Leaf2")
    ;
}
=======================================>

this allows me to do stuff like :

>>> g = Group()
>>> n = g.getChild()
>>> l1 = n.toLeaf1()
>>> if l1:
>>>     print "I'm leaf1"
>>> l2 = n.toLeaf2()
>>> if l2:
>>>     print "I'm leaf2"

Unfortunately it doesn't work, because of the weak references being used 
with return_internal_reference.
It seems that within make_nurse_and_patient (life_support.cpp), a weak 
reference is being
created between the result and the originator. In my case the result can be 
a NULL pointer, failing
the PyWeakref_NewRef function. If however a check is made that the nurse is 
an object supporting
weak references the function continues as intended else returning a PyNone, 
then
my code works. Thus inserting

	if (!PyType_SUPPORTS_WEAKREFS(nurse->ob_type)) {
		Py_INCREF(Py_None);
		return Py_None;
	}

at the beginning of function make_nurse_and_patient would do the trick for 
me. Would
this be possible ?

This brings me to a second point, it seems that life_support_dealloc is 
never called. If it would,
the tp_free would be called for self, which is not initialized ie a NULL 
function pointer.


ciao,

gideon





More information about the Cplusplus-sig mailing list