[C++-sig] Re: The "return always existing pointer throws dangling error" problem
David Abrahams
dave at boost-consulting.com
Wed Oct 22 01:15:08 CEST 2003
"Niall Douglas" <s_sourceforge at nedprod.com> writes:
> 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?
Sometimes, if that's what the policy says to do with it. That doesn't
mean the policy is associated with the object. In the case of
manage_new_object the resulting Python object holds the C++ object
with an auto_ptr, and all information about the policy is lost. There
are other ways to get an identical Python object without using
manage_new_object.
>> > 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?
No, call_method is clearly returning a MyObject*. The "virtual
override in Python" 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)?
Well, of course the Python function doesn't literally override the C++
one; you can't do that since the two languages don't (and couldn't)
have a common ABI. The last actual override of the C++ virtual
function is the one you implement, which invokes call_method. That,
in turn, looks up a Python method with the appropriate name and
invokes it. The only way C++ gets involved again before call_method
picks up the resulting Python object and converts it to C++ is when
that Python method either happens to be a wrapped C++ function
(e.g. the default implementation of MyClass::foo forwarded from the
wrapper class), or when the Python method happens to call some
wrapped C++ function directly or indirectly.
>> > 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?
No, they have many relationships. I'm not sure which kind of
relationship you have in mind, though.
> If so, then wow. How could any transient objects created by
> call_method know their contents are destined for C++ world?
They don't.
> Maybe that's actually the problem?
I have no idea yet. Maybe when you post some *compilable*, *testable*
sample code I'll have some idea.
>> > 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 should've said "minimal but complete".
>> > 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.
I didn't at all; I was just too embarrassed to quote you saying that
;->
>
> Ok, my problem in condensed form (identical to the two problems as
> referenced in the initial post):
I'll be the judge of that... when you post a complete example.
> 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()
^^^^^^^^^
You haven't even given me the code needed to make this line possible.
Please try to make it easy to help you.
--
Dave Abrahams
Boost Consulting
www.boost-consulting.com
More information about the Cplusplus-sig
mailing list