Fix %newobject when used in conjunction with %feature(ref). The code from the ref feature was not always being generated for the function specified by %newobject. Documentation for ref and unref moved from Python to the C++ chapter.

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12783 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2011-08-23 19:29:10 +00:00
commit c794d08597
8 changed files with 262 additions and 160 deletions

View file

@ -38,7 +38,7 @@
<li><a href="#Python_nn25">C++ namespaces</a>
<li><a href="#Python_nn26">C++ templates</a>
<li><a href="#Python_nn27">C++ Smart Pointers</a>
<li><a href="#Python_nn27a">C++ Reference Counted Objects (ref/unref)</a>
<li><a href="#Python_nn27a">C++ reference counted objects</a>
</ul>
<li><a href="#Python_nn28">Further details on the Python class interface</a>
<ul>
@ -2053,147 +2053,11 @@ simply use the <tt>__deref__()</tt> method. For example:
</pre>
</div>
<H3><a name="Python_nn27a"></a>33.3.15 C++ Reference Counted Objects (ref/unref)</H3>
<H3><a name="Python_nn27a"></a>33.3.15 C++ reference counted objects</H3>
<p>
Another usual idiom in C++ is the use of reference counted
objects. Consider for example:
<div class="code">
<pre>
class RCObj {
// implement the ref counting mechanism
int add_ref();
int del_ref();
int ref_count();
public:
virtual ~RCObj() = 0;
int ref() const {
return add_ref();
}
int unref() const {
if (ref_count() == 0 || del_ref() == 0 ) {
delete this;
return 0;
}
return ref_count();
}
};
class A : RCObj {
public:
A();
int foo();
};
class B {
A *_a;
public:
B(A *a) : _a(a) {
a-&gt;ref();
}
~B() {
a-&gt;unref();
}
};
int main() {
A *a = new A();
a-&gt;ref(); // 'a' is ref here
B *b1 = new B(a); // 'a' is ref here
if (1 + 1 == 2) {
B *b2 = new B(a); // 'a' is ref here
delete b2; // 'a' is unref, but not deleted
}
delete b1; // 'a' is unref, but not deleted
a-&gt;unref(); // 'a' is unref and deleted
}
</pre>
</div>
<p>
In the example above, the 'A' class instance 'a' is a reference counted
object, which can't be deleted arbitrarily since it is shared between
the objects 'b1' and 'b2'. 'A' is derived from an Reference Counted
Object 'RCObj', which implements the ref/unref idiom.
</p>
<p>
To tell SWIG that 'RCObj' and all its derived classes are reference
counted objects, you use the "ref" and "unref" features.
For example:
</p>
<div class="code">
<pre>
%module example
...
%feature("ref") RCObj "$this-&gt;ref();"
%feature("unref") RCObj "$this-&gt;unref();"
%include "rcobj.h"
%include "A.h"
...
</pre>
</div>
<p>
where the code passed to the "ref" and "unref" features will be
executed as needed whenever a new object is passed to python, or when
python tries to release the proxy object instance, respectively.
</p>
<p>
In the python side, the use of a reference counted object is not
different than any other regular instance:
</p>
<div class="targetlang">
<pre>
def create_A():
a = A() # SWIG ref 'a' (new object is passed to python)
b1 = B(a) # C++ ref 'a'
if 1 + 1 == 2:
b2 = B(a) # C++ ref 'a'
return a # 'b1' and 'b2' are released, C++ unref 'a' twice
a = create_A()
exit # 'a' is released, SWIG unref 'a'
</pre>
</div>
<p>
Note that the user doesn't explicitly need to call 'a-&gt;ref()' nor 'a-&gt;unref()'
(as neither 'delete a'). Instead, SWIG take cares of executing the "ref"
and "unref" codes as needed. If the user doesn't specify the
"ref/unref" features, SWIG will produce a code equivalent to define
them as:
</p>
<div class="code">
<pre>
%feature("ref") ""
%feature("unref") "delete $this;"
</pre>
</div>
<p>
In other words, SWIG will not do anything special when a new object
is passed to python, and it will always 'delete' the object when
python releases the proxy instance.
The <a href="SWIGPlus.html#SWIGPlus_ref_unref">C++ reference counted objects</a> section contains
Python examples of memory management using referencing counting.
</p>