Qt wiki will be updated on October 12th 2023 starting at 11:30 AM (EEST) and the maintenance will last around 2-3 hours. During the maintenance the site will be unavailable.

PySide Shiboken Words of Advice: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
 
No edit summary
Line 1: Line 1:
=PySide Shiboken Words of Advice=
[toc align_right=&quot;yes&amp;quot; depth=&quot;2&amp;quot;]<br />[[Category:LanguageBindings::PySide]]
 
= PySide Shiboken Words of Advice =


When writing or using Python bindings there is some things you must keep in mind.
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.
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.
Line 9: Line 11:
Let’s see duck punching in action for educational purposes.
Let’s see duck punching in action for educational purposes.


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.
<code><br />import types<br />import Binding
 
obj = Binding.CppClass()
 
# CppClass has a virtual method called 'virtualMethod',
# but we don't like it anymore.<br />def myVirtualMethod(self_obj, arg):<br /> pass


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.
obj.virtualMethod = types.MethodType(myVirtualMethod, obj, Binding.CppClass)<br /></code>


Brief interruption to show what I was saying:
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.


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.
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.
<br />Brief interruption to show what I was saying:
<br /><code><br />import types<br />import Binding
<br />obj = Binding.createCppClass()<br />def myVirtualMethod(self_obj, arg):<br /> pass
<br /># Punching a dead duck…<br />obj.virtualMethod = types.MethodType(myVirtualMethod, obj, Binding.CppClass)<br /></code>
<br />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!
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!


==Python old style classes and PySide==
== Python old style classes and PySide ==


Because of some architectural decisions and deprecated Python types. Since PySide 1.1 old style classes are not supported with multiple inheritance.
Because of some architectural decisions and deprecated Python types. Since PySide 1.1 old style classes are not supported with multiple inheritance.
Line 26: Line 38:


Example with old style class:
Example with old style class:
<code><br />from PySide import QtCore
class MyOldStyleObject:<br /> pass
class MyObject(QtCore, MyOldStyleObject):<br /> pass<br /></code>


this example will raise a ‘TypeError’ due to the limitation on PySide, to fix this you will need use the new style class:
this example will raise a ‘TypeError’ due to the limitation on PySide, to fix this you will need use the new style class:


All classes used for multiple inheritance with other PySide types need to have ‘object’ as base class.
<code><br />from PySide import QtCore


===Categories:===
class MyOldStyleObject(object):<br /> pass


* [[:Category:LanguageBindings|LanguageBindings]]
class MyObject(QtCore, MyOldStyleObject):<br /> pass<br /></code>
** [[:Category:LanguageBindings::PySide|PySide]]

Revision as of 06:40, 24 February 2015

[toc align_right="yes&quot; depth="2&quot;]

PySide Shiboken Words of Advice

When writing or using Python bindings there is some things you must keep in mind.

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.

<br />import types<br />import Binding

obj = Binding.CppClass()

# CppClass has a virtual method called 'virtualMethod',
# but we don't like it anymore.<br />def myVirtualMethod(self_obj, arg):<br /> pass

obj.virtualMethod = types.MethodType(myVirtualMethod, obj, Binding.CppClass)<br />

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:


<br />import types<br />import Binding
<br />obj = Binding.createCppClass()<br />def myVirtualMethod(self_obj, arg):<br /> pass
<br /># Punching a dead duck<br />obj.virtualMethod = types.MethodType(myVirtualMethod, obj, Binding.CppClass)<br />


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!

Python old style classes and PySide

Because of some architectural decisions and deprecated Python types. Since PySide 1.1 old style classes are not supported with multiple inheritance.

Below you can check the examples:

Example with old style class:

<br />from PySide import QtCore

class MyOldStyleObject:<br /> pass

class MyObject(QtCore, MyOldStyleObject):<br /> pass<br />

this example will raise a ‘TypeError’ due to the limitation on PySide, to fix this you will need use the new style class:

<br />from PySide import QtCore

class MyOldStyleObject(object):<br /> pass

class MyObject(QtCore, MyOldStyleObject):<br /> pass<br />