建议之言¶
在编写或使用Python绑定时,有一些事情你必须记住。
右值引用¶
通常情况下,不会为接受右值引用的函数生成绑定。 在6.6版本中已添加了实验性支持。需要使用add-function、declare-function或 function元素显式指定这些函数。对于value-type对象,这没有任何 影响,因为在生成的代码中参数会被复制,并且副本会被移动。然而,对于object-type对象, 这意味着对象实例会被移动,并且不应再被引用。
鸭子类型和虚拟方法¶
鸭子打孔(duck punching)与已实例化对象的类特性修改实践以及封装C++类的虚方法相结合,可能会很棘手。那是一个乐观的说法。
让我们以教育为目的来看看鸭子打孔的实际操作。
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)
如果某些C++代码恰好调用了由“obj” Python对象持有的C++对象上的CppClass::virtualMethod(…),那么新添加的“virtualMethod”方法将被正确调用。这是因为底层的C++对象实际上是一个继承自CppClass的生成C++类的实例,我们称之为CppClassWrapper,它负责接收C++虚方法调用并找到处理此类调用的适当Python重写。
既然你已经了解了这一点,考虑一下当C++有一个工厂方法时的情况,这个方法会给你提供在C++领域中生成的新C++对象,而不是像上面的例子中那样通过使用类构造函数在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)
Binding.createCppClass() 工厂方法只是一个示例,C++ 创建的对象可能由于其他多种原因而出现。以这种方式创建的对象通常会有一个 Python 包装器来持有它们,但持有的对象不是 CppClassWrapper,而是一个普通的 CppClass。所有源自 C++ 的虚方法调用将保持在 C++ 中,永远不会通过鸭子类型覆盖的 Python 虚方法。
尽管鸭子打孔是Python的一个有趣特性,但它与包装的C++虚方法不太兼容,特别是当你无法确定每个包装的C++对象的来源时。总之:不要这样做!
Python 旧式类和 PySide¶
由于一些架构决策和弃用的Python类型。 自PySide 1.1起,旧式类不再支持多重继承。
下面你可以查看示例:
使用旧式类的示例:
from PySide6 import QtCore
class MyOldStyleObject:
pass
class MyObject(QtCore, MyOldStyleObject):
pass
由于PySide的限制,这个例子会引发一个‘TypeError’,要修复这个问题,你需要使用新式类:
from PySide6 import QtCore
class MyOldStyleObject(object):
pass
class MyObject(QtCore, MyOldStyleObject):
pass
所有用于与其他PySide类型进行多重继承的类都需要将‘object’作为基类。
常见问题¶
这是关于Qt for Python的常见问题列表。 欢迎使用我们的邮件列表或我们的IRC频道提出新的条目!
概述¶
什么是Shiboken?¶
Shiboken 是一个生成器运行器插件,用于为 CPython 扩展输出 C++ 代码。 PySide 的第一个版本基于 Boost 模板的源代码。 虽然生成代码更容易,但需要进行范式转变,如下一个问题所解释的。
为什么你从Boost.Python切换到Shiboken?¶
主要原因是尺寸的减小。Boost.Python 过度使用模板,导致二进制文件大小显著增加。另一方面,由于 Shiboken 生成 CPython 代码,生成的二进制文件更小。
创建绑定¶
我可以封装非Qt库吗?¶
是的。查看Shiboken源代码以获取示例(libsample)。
生成的绑定是否有任何运行时依赖?¶
是的。只需要libshiboken,以及显而易见的Python解释器和被包装的C++库。
我需要做什么来创建我的绑定?¶
大部分工作已经由API提取器完成。 开发者创建一个typesystem 文件,其中包含生成代码中所需的任何自定义内容,例如删除类或更改方法签名。 生成器将输出包含CPython代码的.h和.cpp文件,这些代码将为目标库包装Python。
有没有推荐的构建系统?¶
API Extractor 和 generator 都使用并推荐 CMake 构建系统。
我可以使用生成器编写闭源绑定吗?¶
是的,只要你使用LGPL版本的Qt,由于运行时要求。
什么是‘inject code’?¶
这就是我们称之为定制代码的方式,它将被注入到生成的特定位置。它们在类型系统中指定。