类型系统变量¶
用户编写的代码可以使用inject-code标签放置在任意位置。为了简化绑定开发者的工作,注入的代码可以使用特殊变量,这些变量将被正确的值替换。这也保护了开发者免受一些Qt for Python实现细节的影响。
变量¶
- %0
由Python方法/函数包装器的C++返回变量替换。
- %<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的Qt转换调用替换,该调用将Python变量转换为由
CPPTYPE指示的C++变量类型。通常,这是一个变量赋值:
double value = %CONVERTTOCPP[double](pyValue);
指针赋值也是可能的:
void f(double *valuePtr) { *valuePtr = %CONVERTTOCPP[double](pyValue);
但请注意,对于变量定义,类型必须是空格分隔的标记:
double * valuePtr = %CONVERTTOCPP[double](pyValue);
因为否则它将与上面的指针赋值无法区分。
可以使用“auto”作为类型。
- %CONVERTTOPYTHON[CPPTYPE]
被一个用于Python的Qt转换调用所取代,该调用将
CPPTYPE类型的C++变量转换为适当的Python对象。
- %ISCONVERTIBLE[CPPTYPE]
被一个用于Python的Qt“isConvertible”调用所取代,该调用检查Python变量是否可转换为由
CPPTYPE指示的C++变量类型(通过隐式转换或强制转换运算符调用)。
- %CHECKTYPE[CPPTYPE]
被一个用于Python的Qt“checkType”调用所取代,该调用验证Python是否为
CPPTYPE所指示的类型。
- %CPPSELF
被拥有该方法的包装的C++对象实例替换,其中插入了带有此变量的代码。
- %CPPTYPE
替换为拥有插入此变量的代码的C++类的原始名称,不带任何命名空间前缀。它也适用于类级别的代码注入。请注意,
CPPTYPE与%TYPE变量不同,因为后者可能被翻译为原始C++类名称或C++包装类名称。命名空间将被视为类,因此
CPPTYPE也将适用于它们及其包含的函数。
- %FUNCTION_NAME
替换为函数或方法的名称。
- %PYARG_0
替换为Python方法/函数包装器的Python返回变量的名称。
- %PYARG_<number>
类似于
%,但被Python包装方法接收的Python参数(PyObjects)替换。如果在原生代码注入的上下文中使用,即在虚拟方法重写中,
%PYARG_将被转换为Python元组中的一个项目,该元组包含应传递给此虚拟方法的Python重写的参数。示例
long a = PyLong_AS_LONG(%PYARG_1);
等同于
long a = PyLong_AS_LONG(PyTuple_GetItem(%PYTHON_ARGUMENTS, 0));
生成器尝试智能地处理属性,但它仅适用于最简单的情况。
这个例子
Py_DECREF(%PYARG_1); %PYARG_1 = PyLong_FromLong(10);
等同于
Py_DECREF(PyTuple_GetItem(%PYTHON_ARGUMENTS, 0)); PyTuple_SetItem(%PYTHON_ARGUMENTS, 0, PyLong_FromLong(10));
- %PYSELF
被Python包装变量(一个PyObject)替换,该变量表示绑定到接收自定义代码的Python包装方法的实例。
- %PYTHON_ARGUMENTS
替换为由从C++参数转换而来的Python对象组成的Python元组的指针。 这个元组与传递给覆盖C++父类的Python方法的参数相同。
- %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>