建议词#
在编写或使用Python绑定时,需要牢记以下几点。
Rvalue References#
通常,不会为接受rvalue引用的函数生成绑定。在6.6版本中添加了实验性支持。需要使用add-function、declare-function或function元素明确指定函数。对于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文件。
有推荐的构建系统吗?#
API提取器和生成器都使用并推荐CMake构建系统。
我可以使用生成器编写闭源绑定吗?#
是的,只要您使用的是LGPL版本的Qt,因为运行时要求。
“注入代码”是什么?#
这是我们调用将在特定位置被注入的定制代码的方式。它们在类型系统中指定。