类型系统变量

用户编写的代码可以使用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描述中所见,函数的a1a3参数已被移除。如果此函数的任何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, &amp;argc, &amp;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 &lt; argc; ++i)
            delete[] argv[i];
        delete[] argv;
    </inject-code>
</modify-function>