summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcelo Lira <marcelo.lira@openbossa.org>2011-01-12 16:24:10 -0300
committerMarcelo Lira <marcelo.lira@openbossa.org>2011-01-13 10:57:58 -0300
commit2094d56e312a9f35e606cac30aff4bdd0f2dd13d (patch)
tree3811cdcff324b49f548c77d899a532bbada8af12
parentb719c4e8b9238ea8c4d1e022cf597e8cb628f5d7 (diff)
downloadshiboken-2094d56e312a9f35e606cac30aff4bdd0f2dd13d.tar.gz
shiboken-2094d56e312a9f35e606cac30aff4bdd0f2dd13d.tar.xz
shiboken-2094d56e312a9f35e606cac30aff4bdd0f2dd13d.zip
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>
-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 076f3bd3..129a398b 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 6292e952..a9721693 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 00000000..d27cae00
--- /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!
+