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:
parent
86e1051a8b
commit
c794d08597
8 changed files with 262 additions and 160 deletions
|
|
@ -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->ref();
|
||||
}
|
||||
|
||||
~B() {
|
||||
a->unref();
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
A *a = new A();
|
||||
a->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->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->ref();"
|
||||
%feature("unref") RCObj "$this->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->ref()' nor 'a->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>
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue