Menu

#1164 Error when chaining methods in constructor

open
nobody
python (260)
5
2022-03-18
2011-05-11
No

Hi,

I have a wrapped c++ class Foo:

class Foo
{
public:
Foo();

~Foo();

Foo& operator()(int add);

void show();

private:
int value;
};

When using code like:

import foo
f = foo.Foo()(4)

The Foo destructor will be called in the second line, and a call:

f(5)

will result in a broke.

Note that the following code will work as expected:

import foo
f = foo.Foo()
f(5)
f(4)(13)(7)
f.show()

I have tested this code (the project is attached) with swig 2.0.3, python 2.7.1, gcc 4.6.0

Regards,

Discussion

  • Renato Garcia

    Renato Garcia - 2011-05-11

    Project to reproduce the error

     
  • szager

    szager - 2011-05-11

    That is some unusual syntax; I don't think there's an exact equivalent in C++. The closest would be:

    Foo f = Foo()(4);

    ... which is different, in that two Foo objects are constructed, rather than one.

    Anyways, handling that syntax correctly relies on knowing with certainty that Foo::operator() always returns itself, i.e., it always does "return *this;", and that is information which can't be deduced from the method signature. So, supporting this would probably require a feature enhancement to SWIG; something like:

    %feature("returnthis") Foo::operator()(int add);

    Without any enhancements to SWIG, you can work around this with a typemap:

    %typemap(out) Foo& {
    $result = arg1;
    Py_INCREF(arg1);
    }

     
  • Olly Betts

    Olly Betts - 2022-03-18

    Testing the example from the tarball with the commands in the initial report shows this still happens (though I need to also call f.show() to make it crash:

    Python 3.9.10 (main, Feb 22 2022, 13:54:07) 
    [GCC 11.2.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import foo
    >>> f = foo.Foo()(4)
    FOO DESTRUCTION
    >>> f(5)
    <foo.Foo; proxy of <Swig Object of type 'Foo *' at 0x7f7584026d80> >
    >>> f.show()
    malloc(): unaligned tcache chunk detected
    Aborted
    

    SWIG could perhaps in cases where the method returns a reference or pointer to the class type generate a check if it is returning a pointer to itself, though explicit annotation is probably a better answer.

    The suggested workaround doesn't seem to help - I adjusted it to this to get it to even compile:

    %typemap(out) Foo& {
        $result = (PyObject *)$1;
        Py_INCREF($result);
    }
    
     

Log in to post a comment.

MongoDB Logo MongoDB