aboutsummaryrefslogtreecommitdiffstats
path: root/doc
diff options
context:
space:
mode:
authorMarcelo Lira <marcelo.lira@openbossa.org>2011-01-12 16:24:10 -0300
committerHugo Parente Lima <hugo.pl@gmail.com>2012-03-08 16:12:53 -0300
commit78e3c256ff6a154ce8068b3dd7bc551394d73422 (patch)
treeff9491186a25de7d5906bd29b788831a24e451a3 /doc
parent0eef7934bc0dc0a3b915c1502bfc0be60d7eb365 (diff)
Updated Shiboken documentation with advice about duck punching and virtual methods.
Reviewed by Luciano Wolf <luciano.wolf@openbossa.org> Reviewed by Renato Araújo <renato.filho@openbossa.org>
Diffstat (limited to 'doc')
-rw-r--r--doc/_templates/index.html2
-rw-r--r--doc/contents.rst1
-rw-r--r--doc/wordsofadvice.rst71
3 files changed, 74 insertions, 0 deletions
diff --git a/doc/_templates/index.html b/doc/_templates/index.html
index 076f3bd..129a398 100644
--- a/doc/_templates/index.html
+++ b/doc/_templates/index.html
@@ -25,6 +25,8 @@
<span class="linkdescr">support for python sequence protocol</span></p>
<p class="biglink"><a class="biglink" href="{{ pathto("ownership") }}">Object Ownership</a><br/>
<span class="linkdescr">object ownership features</span></p>
+ <p class="biglink"><a class="biglink" href="{{ pathto("wordsofadvice") }}">Words of Advice</a><br/>
+ <span class="linkdescr">Advice for binding developers and users.</span></p>
</td></tr>
</table>
</div>
diff --git a/doc/contents.rst b/doc/contents.rst
index 6292e95..a972169 100644
--- a/doc/contents.rst
+++ b/doc/contents.rst
@@ -10,3 +10,4 @@ Table of contents
codeinjectionsemantics.rst
sequenceprotocol.rst
ownership.rst
+ wordsofadvice.rst
diff --git a/doc/wordsofadvice.rst b/doc/wordsofadvice.rst
new file mode 100644
index 0000000..d27cae0
--- /dev/null
+++ b/doc/wordsofadvice.rst
@@ -0,0 +1,71 @@
+.. _words-of-advice:
+
+***************
+Words of Advice
+***************
+
+When writing or using Python bindings there is some things you must keep in mind.
+
+
+.. _duck-punching-and-virtual-methods:
+
+Duck punching and virtual methods
+=================================
+
+The combination of duck punching, the practice of altering class characteristics
+of already instantiated objects, and virtual methods of wrapped C++ classes, can
+be tricky. That was an optimistic statement.
+
+Let's see duck punching in action for educational purposes.
+
+ .. code-block:: python
+
+ import types
+ import Binding
+
+ obj = Binding.CppClass()
+
+ # CppClass has a virtual method called 'virtualMethod',
+ # but we don't like it anymore.
+ def myVirtualMethod(self_obj, arg):
+ pass
+
+ obj.virtualMethod = types.MethodType(myVirtualMethod, obj, Binding.CppClass)
+
+
+If some C++ code happens to call `CppClass::virtualMethod(...)` on the C++ object
+held by "obj" Python object, the new duck punched "virtualMethod" method will be
+properly called. That happens because the underlying C++ object is in fact an instance
+of a generated C++ class that inherits from `CppClass`, let's call it `CppClassWrapper`,
+responsible for receiving the C++ virtual method calls and finding out the proper Python
+override to which handle such a call.
+
+Now that you know this, consider the case when C++ has a factory method that gives you
+new C++ objects originated somewhere in C++-land, in opposition to the ones generated in
+Python-land by the usage of class constructors, like in the example above.
+
+Brief interruption to show what I was saying:
+
+ .. code-block:: python
+
+ import types
+ import Binding
+
+ obj = Binding.createCppClass()
+ def myVirtualMethod(self_obj, arg):
+ pass
+
+ # Punching a dead duck...
+ obj.virtualMethod = types.MethodType(myVirtualMethod, obj, Binding.CppClass)
+
+
+The `Binding.createCppClass()` factory method is just an example, C++ created objects
+can pop out for a number of other reasons. Objects created this way have a Python wrapper
+holding them as usual, but the object held is not a `CppClassWrapper`, but a regular
+`CppClass`. All virtual method calls originated in C++ will stay in C++ and never reach
+a Python virtual method overridden via duck punching.
+
+Although duck punching is an interesting Python feature, it don't mix well with wrapped
+C++ virtual methods, specially when you can't tell the origin of every single wrapped
+C++ object. In summary: don't do it!
+