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

@ -4618,6 +4618,180 @@ p = f.__deref__() # Raw pointer from operator->
<b>Note:</b> Smart pointer support was first added in SWIG-1.3.14.
</p>
<H2><a name="SWIGPlus_ref_unref"></a>C++ reference counted objects - ref/unref feature</H2>
<p>
Another similar 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(); // (count: 0)
a-&gt;ref(); // 'a' ref here (count: 1)
B *b1 = new B(a); // 'a' ref here (count: 2)
if (1 + 1 == 2) {
B *b2 = new B(a); // 'a' ref here (count: 3)
delete b2; // 'a' unref, but not deleted (count: 2)
}
delete b1; // 'a' unref, but not deleted (count: 1)
a-&gt;unref(); // 'a' unref and deleted (count: 0)
}
</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 a <i>Reference Counted
Object</i> 'RCObj', which implements the ref/unref idiom.
</p>
<p>
To tell SWIG that 'RCObj' and all its derived classes are reference
counted objects, use the "ref" and "unref" <a href="Customization.html#Customization_features">features</a>.
These are also available as <tt>%refobject</tt> and <tt>%unrefobject</tt>, respectively.
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>
On the python side, the use of a reference counted object is no
different to any other regular instance:
</p>
<div class="targetlang">
<pre>
def create_A():
a = A() # SWIG ref 'a' - new object is passed to python (count: 1)
b1 = B(a) # C++ ref 'a (count: 2)
if 1 + 1 == 2:
b2 = B(a) # C++ ref 'a' (count: 3)
return a # 'b1' and 'b2' are released and deleted, C++ unref 'a' twice (count: 1)
a = create_A() # (count: 1)
exit # 'a' is released, SWIG unref 'a' called in the destructor wrapper (count: 0)
</pre>
</div>
<p>
Note that the user doesn't explicitly need to call 'a-&gt;ref()' nor 'a-&gt;unref()'
(and neither 'delete a'). Instead, SWIG takes cares of executing the "ref"
and "unref" calls as needed. If the user doesn't specify the
"ref/unref" feature for a type, SWIG will produce code equivalent to defining these
features:
</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 underlying object when
python releases the proxy instance.
</p>
<p>
</p>
<p>
The <a href="Customization.html#Customization_ownership">%newobject feature</a> is designed to indicate to
the target language that it should take ownership of the returned object.
When used in conjunction with a type that has the "ref" feature associated with it, it additionally emits the
code in the "ref" feature into the C++ wrapper.
Consider wrapping the following factory function in addition to the above:
</p>
<div class="code">
<pre>
%newobject AFactory;
A *AFactory() {
return new A();
}
</pre>
</div>
<p>
The <tt>AFactory</tt> function now acts much like a call to the <tt>A</tt> constructor with respect to memory handling:
</p>
<div class="targetlang">
<pre>
a = AFactory() # SWIG ref 'a' due to %newobject (count: 1)
exit # 'a' is released, SWIG unref 'a' called in the destructor wrapper (count: 0)
</pre>
</div>
<H2><a name="SWIGPlus_nn35"></a>6.25 Using declarations and inheritance</H2>