类型系统变量#
用户编写的代码可以使用 inject-code 标签放置在任意位置。为了简化绑定开发者的工作,注入的代码可以利用将被正确值替换的特殊变量。这也可以保护开发者免受Qt for Python实现的一些特定细节的影响。
变量#
- %0
由Python方法/函数包装器的C++返回变量替换。
- %<number>
由
<number>
指示位置的C++参数的名称替换。参数计数从%1
开始,因为%0
代表返回变量名称。如果数字指示在类型系统描述中已删除的变量,但为其提供了默认值,则将使用该值。考虑以下示例void argRemoval(int a0, int a1 = 123);
<modify-function signature="argRemoval(int, int)"> <modify-argument index="2"> <remove-argument/> </modify-argument> </modify-function>
%1
将被C++参数名称替换,且%2
将获取值为123
。
- %ARGUMENT_NAMES
由所有在方法/函数的类型系统描述中没有删除的C++参数的名称组成的逗号分隔列表替换。如果删除的参数有一个默认值(原始的或类型系统中提供的),则将在参数列表中插入该值。如果要完全删除参数,使其不以任何形式出现在
%ARGUMENT_NAMES
替换中,请勿忘记使用 remove-default-expression 类型系统标签删除其默认值。以下方法和相关类型系统描述为例
void argRemoval(int a0, Point a1 = Point(1, 2), bool a2 = true, Point a3 = Point(3, 4), int a4 = 56);
<modify-function signature="argRemoval(int, Point, bool, Point, int)"> <modify-argument index="2"> <remove-argument/> <replace-default-expression with="Point(6, 9)"/> </modify-argument> <modify-argument index="4"> <remove-argument/> </modify-argument> </modify-function>
如XML描述中所示,函数的
a1
和a3
参数已被删除。如果此函数的任何inject-code
使用%ARGUMENT_NAMES
,则生成的列表将等效于此方式使用单个参数类型系统变量%1, Point(6, 9), %3, Point(3, 4), %5
- %ARG#_TYPE
由指示的代码
#
位置的 C++ 参数的类型所替换。参数计数从%1
开始,因为%0
在其他上下文中表示返回变量,但%ARG0_TYPE
将不会转换为返回类型,因为这已经由 %RETURN_TYPE 变量完成。示例void argRemoval(int a0, int a1 = 123);
<modify-function signature="argRemoval(int, int)"> <modify-argument index="2"> <remove-argument/> </modify-argument> </modify-function>
%1
将被C++参数名称替换,且%2
将获取值为123
。
- %CONVERTTOCPP[CPPTYPE]
由将 Python 变量转换为类型由
CPPTYPE
指示的 C++ 变量的 Qt for Python 转换调用所替换。这通常是一个变量赋值
double value = %CONVERTTOCPP[double](pyValue);
指针赋值也是可能的
void f(double *valuePtr) { *valuePtr = %CONVERTTOCPP[double](pyValue);
但是请注意,对于变量定义,类型必须是空格分隔的标记
double * valuePtr = %CONVERTTOCPP[double](pyValue);
因为否则将无法区分上面的指针赋值。
可以使用“auto”作为类型。
- %CONVERTTOPYTHON[CPPTYPE]
由将类型由
CPPTYPE
指示的 C++ 变量转换为合适的 Python 对象的 Qt for Python 转换调用所替换。
- %ISCONVERTIBLE[CPPTYPE]
由一个 Qt for Python “isConvertible” 调用以检查一个 Python 变量是否可以转换(通过显式转换或算子调用)为类型由
CPPTYPE
指示的 C++ 变量所替换。
- %CHECKTYPE[CPPTYPE]
由一个 Qt for Python “checkType” 调用以验证一个 Python 对象的类型是否由
CPPTYPE
指示。
- %CPPSELF
由拥有此变量插入的代码中的方法的封装 C++ 对象实例所替换。
- %CPPTYPE
由拥有此变量插入的代码中的方法的 C++ 类的原始名称(不带任何命名空间前缀)所替换。它将适用于类级别代码注入。注意,
CPPTYPE
与 %TYPE 变量不同,因为后者可能被转换为原始 C++ 类名或 C++ 封装类名。命名空间被视为类,因此
CPPTYPE
也适用于它们及其嵌套的函数。
- %FUNCTION_NAME
替换为一个函数或方法的名称。
- %PYARG_0
替换为 Python 方法/函数包装器的 Python 返回变量的名称。
- %PYARG_<number>
类似于
%<number>
,但被替换为由 Python 包装器方法接收的 Python 参数(PyObjects)所替换。如果在原生代码注入的上下文中使用,即在一个虚拟方法覆盖中,
%PYARG_<number>
将被转换为传递给 Python 覆盖此虚拟方法的 Python 元组的单个项目。该示例
long a = PyLong_AS_LONG(%PYARG_1);
相当于
long a = PyLong_AS_LONG(PyTuple_GET_ITEM(%PYTHON_ARGUMENTS, 0));
生成器在赋值方面试图保持智能,但它只能对最简单的案例工作。
此示例
Py_DECREF(%PYARG_1); %PYARG_1 = PyLong_FromLong(10);
相当于
Py_DECREF(PyTuple_GET_ITEM(%PYTHON_ARGUMENTS, 0)); PyTuple_SET_ITEM(%PYTHON_ARGUMENTS, 0, PyLong_FromLong(10));
- %PYSELF
替换为表示与 Python 包装器方法绑定并接收自定义代码的实例的 Python 包装器变量(PyObject)。
- %PYTHON_ARGUMENTS
替换为包含从 C++ 参数转换为 Python 对象的 Python 元组的指针。该元组与传递给 Python 方法以覆盖 C++ 父级方法相同的参数传递。
- %PYTHON_METHOD_OVERRIDE
此变量仅在本地方法代码注入中使用,即用于C++虚方法的绑定覆盖上。它被Python方法覆盖的指针所替换。
- %PYTHONTYPEOBJECT
由插入上下文中的Python类型对象替换:方法或类修改。
- %BEGIN_ALLOW_THREADS
由线程状态保存程序替换。必须与%END_ALLOW_THREADS变量匹配。
- %END_ALLOW_THREADS
由线程状态恢复程序替换。必须与%BEGIN_ALLOW_THREADS变量匹配。
- %RETURN_TYPE
由函数或方法返回的类型替换。
- %TYPE
由函数所属的类名称替换。可在方法或类级别的代码注入中使用。
示例
仅为了说明上一节中描述的变量用法,以下是Qt for Python测试类型系统描述的摘录。它将接受argc/argv
参数的方法更改为期望Python序列的方法。
<modify-function signature="overloadedMethod(int, char**)">
<modify-argument index="1">
<replace-type modified-type="PySequence" />
</modify-argument>
<modify-argument index="2">
<remove-argument />
</modify-argument>
<inject-code class="target" position="beginning">
int argc;
char** argv;
if (!PySequence_to_argc_argv(%PYARG_1, &argc, &argv)) {
PyErr_SetString(PyExc_TypeError, "error");
return 0;
}
%RETURN_TYPE foo = %CPPSELF.%FUNCTION_NAME(argc, argv);
%0 = %CONVERTTOPYTHON[%RETURN_TYPE](foo);
for (int i = 0; i < argc; ++i)
delete[] argv[i];
delete[] argv;
</inject-code>
</modify-function>