[C++-sig] Re: The "return always existing pointer throws dangling error" problem

Niall Douglas s_sourceforge at nedprod.com
Wed Oct 22 00:45:00 CEST 2003


On 21 Oct 2003 at 16:30, David Abrahams wrote:

> > Let me clarify: From what I understand, most return policies destroy
> > their associated C++ object instance when its python representation
> > expires. Mostly that's a copy of the C++ object instance and when
> > this is the case, the throwing of the error is correct.
> >
> > However, if the object instance was allocated by new (and thus its
> > policy was manage_new_object), 
> 
> Objects don't have call policies; those are associated with
> methods/functions.

I had thought that when a function with a return policy returns 
object X, the lifetime ie; validity of X is tied to something else?

> > return_internal_reference is also different - if you attach lifetime
> > to self which most do, then when a virtual override in python
> > returns an internal reference 
> 
> ?? huh ??
> A virtual override in Python can only return a Python object.
> There's no such thing as an "internal reference" in that context.

So when there is a virtual MyObject *MyClass::foo() and my wrapper of 
MyClass overrides default foo() with one calling call_method<MyObject 
*>(self, "foo") then call_method is returning a python object?

How can that possibly be when foo() and all overrides of it must 
return MyObject * (with the exception of covariant returns)?

> > to either C++ or python code invoking that function
> 
> When a virtual function overridden in Python is invoked from Python,
> C++ and BPL are never involved.  The function is simply looked up and
> called in the usual Python way.  When invoked from C++, the call
> policies are never involved, since they only apply to wrapped C++
> functions and a Python function is actually being called.

So you're saying that the _class.def() part has absolutely zero 
relation to the call_method part? They are two bits of absolutely 
unrelated code?

If so, then wow. How could any transient objects created by 
call_method know their contents are destined for C++ world? Maybe 
that's actually the problem?

> > surely BPL is attaching the lifetime of the internal reference to
> > the "self" instance and not to the temporary object created during
> > call_method?  Therefore surely the error is reporting the wrong
> > thing dangling?
> 
> Given everything I've written above, what you're saying makes no
> sense to me.

Once again, I appear to misunderstand how BPL works :(

> More details about your problem are needed.  My suggestion: for the
> time-being, stop trying to second-guess the design of Boost.Python and
> just describe what you're trying to do with a *minimal example*.  If
> we can't come up with a good solution, then we can talk about design
> changes.

Done below.

> > I appreciate that this has been addressed before, and that Dave who
> > is <censored> has said he's not sure about the correct solution. 
> > But I can't see how BPL doesn't know where one of its own pointer
> > containers got its pointer from?

Err, the <censored> bit was saying a compliment, not anything 
negative in any way whatsoever - I was using a construct borrowed 
from German (consequence of being European). My apologies if you took 
offense at that.

Ok, my problem in condensed form (identical to the two problems as 
referenced in the initial post):

namespace FX {
class FXMetaClass;

class FXObject
{
public:
    static const FXMetaClass metaClass; // metadata for this subclass
    virtual const FXMetaClass *getMetaClass() const { return 
&metaClass; } // metadata for most derived subclass
};

class FXApp : public FXObject
{ ... };
};

struct FX_FXObject_Wrapper: FX::FXObject
{
    const FX::FXMetaClass* getMetaClass() const {
        return call_method< const FX::FXMetaClass* >(self, 
"getMetaClass");
    }

    const FX::FXMetaClass* default_getMetaClass() const {
        return FX::FXObject::getMetaClass();
    }
};

...
void Export_FXObject()
{
    class_< FX::FXObject, FX_FXObject_Wrapper >("FXObject", init<  
>())
        .def("getMetaClass", &FX::FXObject::getMetaClass, 
&FX_FXObject_Wrapper::default_getMetaClass, 
return_internal_reference< 1 >())
        ;
    class_< FX::FXMetaClass >("FXMetaClass", init< const 
FX::FXMetaClass& >())
    ...
}

And when you do in python:
a=FXApp()
a.init();

And in FXApp::init(), it queries its metadata:
FXMetaClass *mc=getMetaClass();

... BPL calls FX_FXObject_Wrapper::getMetaClass(), which calls 
python's self.getMetaClass() by call_method (except there isn't one 
and thus it calls the C++ default). However on return from 
call_method, it throws:

ReferenceError: Attempt to return dangling pointer to object of type: 
class FX::FXMetaClass

As I previously said, it's the identical problem as previous posts 
have had. However, in none of those previous posts did I see what a 
solution would be including permitting the python side to subclass 
FXApp say and provide its own custom FXMetaClass.

BTW, the code design of FXObject's and FXMetaClass' is all not mine, 
it is of the underlying GUI toolkit FOX.

Cheers,
Niall




-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 208 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20031021/0cc5784e/attachment.pgp>


More information about the Cplusplus-sig mailing list