fix inplace python opers
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@5859 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
be31340148
commit
fd1c9fb316
2 changed files with 82 additions and 10 deletions
|
|
@ -18,16 +18,6 @@
|
|||
%rename(__or__) *::operator|;
|
||||
%rename(__xor__) *::operator^;
|
||||
%rename(__invert__) *::operator~;
|
||||
%rename(__iadd__) *::operator+=;
|
||||
%rename(__isub__) *::operator-=;
|
||||
%rename(__imul__) *::operator*=;
|
||||
%rename(__idiv__) *::operator/=;
|
||||
%rename(__imod__) *::operator%=;
|
||||
%rename(__ilshift__) *::operator<<=;
|
||||
%rename(__irshift__) *::operator>>=;
|
||||
%rename(__iand__) *::operator&=;
|
||||
%rename(__ior__) *::operator|=;
|
||||
%rename(__ixor__) *::operator^=;
|
||||
%rename(__lt__) *::operator<;
|
||||
%rename(__le__) *::operator<=;
|
||||
%rename(__gt__) *::operator>;
|
||||
|
|
@ -48,4 +38,60 @@
|
|||
%ignorewarn("386:operator->* ignored") operator->*;
|
||||
%ignorewarn("389:operator[] ignored (consider using %extend)") operator[];
|
||||
|
||||
/*
|
||||
Inplace operator declarations.
|
||||
|
||||
They translate the inplace C++ operators (+=, -=, ...) into the
|
||||
corresponding python equivalents(__iadd__,__isub__), etc,
|
||||
disabling the ownership of the input 'self' pointer, and assigning
|
||||
it to the returning object:
|
||||
|
||||
%feature("self:disown") *::Operator;
|
||||
%feature("new") *::Operator;
|
||||
|
||||
This makes the most common case safe, ie:
|
||||
|
||||
A& A::operator+=(int i) { ...; return *this; }
|
||||
^^^^ ^^^^^^
|
||||
|
||||
will work fine, even when the resulting python object shares the
|
||||
'this' pointer with the input one. The input object is usually
|
||||
deleted after the operation, including the shared 'this' pointer,
|
||||
producing 'strange' seg faults, as reported by Lucriz
|
||||
(lucriz@sitilandia.it).
|
||||
|
||||
If you have an interface that already takes care of that, ie, you
|
||||
already are using inplace operators and you are not getting
|
||||
seg. faults, with the new scheme you could end with 'free' elements
|
||||
that never get deleted (maybe, not sure, it depends). But if that is
|
||||
the case, you could recover the old behaviour using
|
||||
|
||||
%feature("self:disown","") A::operator+=;
|
||||
%feature("new","") A::operator+=;
|
||||
|
||||
which recovers the old behaviour for the class 'A', or if you are
|
||||
100% sure your entire system works fine in the old way, use:
|
||||
|
||||
%feature("self:disown","") *::operator+=;
|
||||
%feature("new","") *::operator+=;
|
||||
|
||||
*/
|
||||
|
||||
%define %swig_inplace_oper(Oper, PyOper)
|
||||
%feature("self:disown") *::Oper;
|
||||
%feature("new") *::Oper;
|
||||
%rename(__##PyOper##__) *::Oper;
|
||||
%enddef
|
||||
|
||||
%swig_inplace_oper(operator +=, iadd);
|
||||
%swig_inplace_oper(operator -=, isub);
|
||||
%swig_inplace_oper(operator *=, imul);
|
||||
%swig_inplace_oper(operator /=, idiv);
|
||||
%swig_inplace_oper(operator %=, imod);
|
||||
%swig_inplace_oper(operator &=, iand);
|
||||
%swig_inplace_oper(operator |=, ior);
|
||||
%swig_inplace_oper(operator ^=, ixor);
|
||||
%swig_inplace_oper(operator <<=, ilshift);
|
||||
%swig_inplace_oper(operator >>=, irshift);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -624,6 +624,32 @@ Swig_MethodToFunction(Node *n, String *classname, int flags) {
|
|||
SwigType_add_pointer(type);
|
||||
p = NewParm(type,"self");
|
||||
Setattr(p,"hidden","1");
|
||||
/*
|
||||
Disable the 'this' ownership in 'self' to manage inplace
|
||||
operations like:
|
||||
|
||||
A& A::operator+=(int i) { ...; return *this;}
|
||||
|
||||
Here the 'self' parameter ownership needs to be disabled since
|
||||
there could be two objects sharing the same 'this' pointer: the
|
||||
input and the result one. And worse, the pointer could be deleted
|
||||
in one of the objects (input), leaving the other (output) with
|
||||
just a seg. fault to happen.
|
||||
|
||||
To avoid the previous problem, use
|
||||
|
||||
%feature("self:disown") *::operator+=;
|
||||
%feature("new") *::operator+=;
|
||||
|
||||
These two lines just transfer the ownership of the 'this' pointer
|
||||
from the input to the output wrapping object.
|
||||
|
||||
This happens in python, but may also happens in other target
|
||||
languages.
|
||||
*/
|
||||
if (Getattr(n,"feature:self:disown")) {
|
||||
Setattr(p,"wrap:disown",Getattr(n,"feature:self:disown"));
|
||||
}
|
||||
set_nextSibling(p,parms);
|
||||
Delete(type);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue