建议词#

在编写或使用Python绑定时,需要牢记以下几点。

Rvalue References#

通常,不会为接受rvalue引用的函数生成绑定。在6.6版本中添加了实验性支持。需要使用add-functiondeclare-functionfunction元素明确指定函数。对于value-type对象,由于在生成的代码中arguments被复制,这次复制将解除,所以没有任何影响。但是,对于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 override。

现在你知道这个,考虑当C++有一个工厂方法,从C++-land的某个地方创建新的C++对象的情况,与如上例中所示的Python-land中使用类构造函数创建的由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提取器完成。开发者创建一个包含所需自定义的类型系统文件,如删除类或更改方法签名。生成器将输出带有将为目标库包裹的CPython代码的.h.cpp文件。

我可以使用生成器编写闭源绑定吗?#

是的,只要您使用的是LGPL版本的Qt,因为运行时要求。

“注入代码”是什么?#

这是我们调用将在特定位置被注入的定制代码的方式。它们在类型系统中指定。