建议之言

在编写或使用Python绑定时,有一些事情你必须记住。

右值引用

通常情况下,不会为接受右值引用的函数生成绑定。 在6.6版本中已添加了实验性支持。需要使用add-functiondeclare-functionfunction元素显式指定这些函数。对于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。

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

是的,只要你使用LGPL版本的Qt,由于运行时要求。

什么是‘inject code’?

这就是我们称之为定制代码的方式,它将被注入到生成的特定位置。它们在类型系统中指定。