aboutsummaryrefslogtreecommitdiff
path: root/Doc
diff options
context:
space:
mode:
authorWilliam S Fulton <wsf@fultondesigns.co.uk>2019-01-08 21:34:27 +0000
committerWilliam S Fulton <wsf@fultondesigns.co.uk>2019-01-08 21:34:27 +0000
commitc2e811c12da35bef5d6089269e4d09d598335740 (patch)
tree8940f78198de4488d4f82ec1f0f8fa0b7efafe84 /Doc
parent4e4bb54fe7f01432825a1e0bcc1ffde7bd822271 (diff)
parent26e08be7ce465799ad9f40f2e0781b4780581454 (diff)
downloadswig-c2e811c12da35bef5d6089269e4d09d598335740.tar.gz
Merge branch 'jakecobb-python-memory-docs'
* jakecobb-python-memory-docs: -builtin compatible ref example in Python docs %pythonappend docs and memory management example
Diffstat (limited to 'Doc')
-rw-r--r--Doc/Manual/Python.html125
1 files changed, 125 insertions, 0 deletions
diff --git a/Doc/Manual/Python.html b/Doc/Manual/Python.html
index 8d1678a7f..6f8e1ddfa 100644
--- a/Doc/Manual/Python.html
+++ b/Doc/Manual/Python.html
@@ -100,6 +100,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>
@@ -3572,6 +3573,7 @@ proxy, just before the return statement.
%feature("pythonappend") Foo::bar(int) %{
#do something after C++ call
+ #the 'val' variable holds the return value
%}
@@ -3601,6 +3603,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
%}
@@ -5432,6 +5435,128 @@ 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.
+</p>
+
+<p>
+You can do this by adding the reference when the <tt>getWheel()</tt> method
+is called using one of two approaches:
+</p>
+
+<p>
+The easier, but less optimized, way is to use 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>
+
+<p>
+The second option, which performs better and is required if you use the
+<tt>-builtin</tt> option, is to set the reference in the CPython implementation:
+
+<div class="code">
+<pre>
+%fragment("extra_reference", "header") {
+
+static PyObject *extra_reference() {
+ static PyObject *extra_reference_string = NULL;
+ if (!extra_reference_string)
+ extra_reference_string = SWIG_Python_str_FromChar("_extra_reference");
+ return extra_reference_string;
+}
+
+}
+
+%extend Wheel {
+%typemap(ret, fragment="extra_reference") Wheel& getWheel %{
+ // A reference to the parent class is added to ensure the underlying C++
+ // object is not deleted while the item is in use
+ PyObject_SetAttr($result, extra_reference(), $self);
+%}
+/* FYI: Alternative approach, but is possibly harder to understand, so suggest above
+%typemap(out, fragment="extra_reference") Wheel& getWheel %{
+ $typemap(out, Wheel &)
+ // A reference to the parent class is added to ensure the underlying C++
+ // object is not deleted while the item is in use
+ PyObject_SetAttr($result, extra_reference(), $self);
+%}
+*/
+}
+</pre>
+</div>
<H2><a name="Python_nn65">38.10 Docstring Features</a></H2>