类型系统变量#

用户编写的代码可以使用 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描述中所示,函数的 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 变量转换为类型由 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, &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>