Re: C++ to Python and returning members of a C++ object
William S Fulton <[email protected]>
| Newsgroups | gmane.comp.programming.swig |
|---|---|
| Message-ID | <CANGqftB4Zp90gbwTyoyNAn189S3O-kUaj8OVzQ--L35DTRdbqQ@mail.gmail.com> |
Hi Terry
This is one of the most horrible problem areas mixing languages, that is,
memory management. Here is some background reading:
http://www.swig.org/Doc4.0/Python.html#Python_memory_management_member_variables
https://github.com/swig/swig/issues/945
https://github.com/swig/swig/pull/1234
Below is one way you can fix this (it's a variation of returning members by
reference documented in the 1st link above). Note that SWIG uses pointers
for accessing non-primitive member variables, see
http://www.swig.org/Doc4.0/SWIG.html#SWIG_structure_data_members.
%fragment("member_parent_attribute_init", "init") {
// thread safe initialization
member_parent_attribute();
}
%fragment("member_parent_attribute", "header",
fragment="member_parent_attribute_init") {
static PyObject* member_parent_attribute() {
static PyObject* attr = SWIG_Python_str_FromChar("__member_parent");
return attr;
}
}
%typemap(ret, fragment="member_parent_attribute", noblock=1) ListA
*TypeB::list1 %{
PyObject_SetAttr($result, member_parent_attribute(), $self);
%}
William
On Thu, 25 Jun 2020 at 14:58, Terry Barnaby <[email protected]> wrote:
> I have had a quick look at the SWIG code.
>
> It seems that it would be possible, and desirable to do a Py_INCREF() on
> the PyObject* object that is wrapping the C++ object which you are
> returning a pointer to the member from. This would hold the whole 'C++'
> object in memory so that returning a pointer to one of this objects
> members would be ok. The PyObject* returned for the member would have to
> have a pointer to its parents PyObject* and do a Py_DECREF() on the
> parent object when it is finally deleted so that the original C++ object
> gets cleaned up eventually.
>
> I don't know the SWIG code to know if this is really possible and if
> people think this is a reasonable SWIG feature that could be added ?
> At the moment a user of your SWIG generated Python API gets a pointer to
> a destroyed object which is not good.
>
> Terry
> On 24/06/2020 10:04, Terry Barnaby wrote:
> > I have a class library that has List objects as members of the class.
> > If I use this class in a Python function and try to return one of
> > these more complex members all hell breaks loose. It appears the SWIG
> > generated wrapper returns a pointer to the objects member rather than
> > making a copy of it when returning the member from the function.
> >
> > So I have something like:
> >
> > class TypeB {
> >
> > public:
> >
> > List<TypeA> list1;
> >
> > };
> >
> > If in Python I have a function like the following, the returned item
> > is effectively (SWIG wrapped) a pointer the b objects member and b
> > disappears when the function returns.
> >
> > def func1():
> >
> > b = TypeB();
> >
> > b.list1.append(TypeA());
> >
> > return b.list1;
> >
> > Now I can use "return ListTypeA(b.list1)", where ListTypeA has been
> > declared using a %template declaration such that the copy constructor
> > is called to explicitly make a copy of the list, but is there a better
> > way of handing this ?
> >
> > I know this is difficult to handle, but perhaps something like a
> > %template(return) to add code when returning a type in a Python
> > function somehow or maybe the overall objects reference counter can be
> > incremented ?
> >
> >
> >
> > _______________________________________________
> > Swig-user mailing list
> > [email protected]
> > https://lists.sourceforge.net/lists/listinfo/swig-user
>
>
>
>
> _______________________________________________
> Swig-user mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/swig-user
>
_______________________________________________
Swig-user mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/swig-user