%pythonappend docs and memory management example

Document 'val' variable for the %pythonappend directive.
Add memory management example equivalent to Java and C#
docs using %pythonappend.
This commit is contained in:
Jake Cobb 2017-02-28 11:24:08 -05:00 committed by Jake Cobb
commit 4ae4fe8a42

View file

@ -96,6 +96,7 @@
<li><a href="#Python_nn62">Mapping Python tuples into small arrays</a>
<li><a href="#Python_nn63">Mapping sequences to C arrays</a>
<li><a href="#Python_nn64">Pointer handling</a>
<li><a href="#Python_memory_management_member_variables">Memory management when returning references to member variables</a>
</ul>
<li><a href="#Python_nn65">Docstring Features</a>
<ul>
@ -3543,6 +3544,7 @@ proxy, just before the return statement.
%feature("pythonappend") Foo::bar(int) %{
#do something after C++ call
#the 'val' variable holds the return value
%}
@ -3572,6 +3574,7 @@ SWIG version 1.3.28 you can use the directive forms
%pythonappend Foo::bar(int) %{
#do something after C++ call
#the 'val' variable holds the return value
%}
@ -5267,6 +5270,85 @@ that has a <tt>this</tt> attribute. In addition,
class object (if applicable).
</p>
<H3><a name="Python_memory_management_member_variables">36.9.7 Memory management when returning references to member variables</a></H3>
<p>
This example shows how to prevent premature garbage collection of objects when the underlying C++ class returns a pointer or reference to a member variable.
The example is a direct equivalent to this <a href="Java.html#Java_memory_management_objects">Java equivalent</a>.
</p>
<p>
Consider the following C++ code:
</p>
<div class="code">
<pre>
struct Wheel {
int size;
Wheel(int sz) : size(sz) {}
};
class Bike {
Wheel wheel;
public:
Bike(int val) : wheel(val) {}
Wheel&amp; getWheel() { return wheel; }
};
</pre>
</div>
<p>
and the following usage from Python after running the code through SWIG:
</p>
<div class="code">
<pre>
bike = Bike(10)
wheel = bike.getWheel()
print("wheel size: {}".format(wheel.size))
del bike # Allow bike to be garbage collected
print("wheel size: {}".format(wheel.size))
</pre>
</div>
<p>
Don't be surprised that if the resulting output gives strange results such as...
</p>
<div class="shell">
<pre>
wheel size: 10
wheel size: 135019664
</pre>
</div>
<p>
What has happened here is the garbage collector has collected the <tt>Bike</tt> instance as it doesn't think it is needed any more.
The proxy instance, <tt>wheel</tt>, contains a reference to memory that was deleted when the <tt>Bike</tt> instance was collected.
In order to prevent the garbage collector from collecting the <tt>Bike</tt> instance, a reference to the <tt>Bike</tt> must
be added to the <tt>wheel</tt> instance. You can do this by adding the reference when the <tt>getWheel()</tt> method
is called using the typemap-like <tt>%pythonappend</tt> directive (see <a href="#Python_nn42">36.6.2 Adding additional Python code</a>):
</p>
<div class="code">
<pre>
%pythonappend getWheel %{
# val is the Wheel proxy, self is the Bike instance
val._bike = self
%}
</pre>
</div>
<p>
The code gets appended to the Python code generated for the
<tt>Bike::getWheel</tt> function, where we store the <tt>Bike</tt> proxy
instance onto the <tt>Wheel</tt> proxy instance before it is returned to the
caller.
</p>
<H2><a name="Python_nn65">36.10 Docstring Features</a></H2>