diff options
author | Marcelo Lira <marcelo.lira@openbossa.org> | 2009-11-21 23:10:46 -0300 |
---|---|---|
committer | Marcelo Lira <marcelo.lira@openbossa.org> | 2009-11-23 11:48:03 -0300 |
commit | e85fcb77b2f1c9db7fbb3008d073609bf710190a (patch) | |
tree | a41f1e0deaf917f61e6f96441233feefb38079db | |
parent | 8560b8437fdc84f16221cabb37397f092f52e087 (diff) |
Added the type system %PYTHON_ARGUMENTS variable. It is used in
"native" code injections to get the Python tuple of objects converted
from C++ arguments received from a virtual method call. The tuple is
the one to be passed to a Python override of the wrapped C++ virtual
method.
Other type system variables were improved to have a smarter replacement
depending if they are part of a code injection of the "native" or "target"
classes.
* %PYARG_#
In the context of a native code injection it represents one item in the
Python argument tuple, acquired with PyTuple_GET_ITEM. If the binding
developer attributes some value to the variable the code snippet writer
tries to be smart and sets the tuple item with PyTuple_SET_ITEM.
See the updated documentation for more details.
* %CPPSELF
Replaced by "this" in native code injections.
The documentation was updated with the new information.
-rw-r--r-- | doc/typesystemvariables.rst | 47 | ||||
-rw-r--r-- | shibokengenerator.cpp | 108 |
2 files changed, 117 insertions, 38 deletions
diff --git a/doc/typesystemvariables.rst b/doc/typesystemvariables.rst index ff4a0e34f..dbfc29350 100644 --- a/doc/typesystemvariables.rst +++ b/doc/typesystemvariables.rst @@ -150,6 +150,43 @@ Variables Similar to ``%#``, but is replaced by the Python arguments (PyObjects) received by the Python wrapper method. + If used in the context of a native code injection, i.e. in a virtual method + override, ``%PYARG_#`` will be translated to one item of the Python tuple + holding the arguments that should be passed to the Python override for this + virtual method. + + The example + + .. code-block:: c++ + + long a = PyInt_AS_LONG(%PYARG_1); + + + is equivalent of + + .. code-block:: c++ + + long a = PyInt_AS_LONG(PyTuple_GET_ITEM(%PYTHON_ARGUMENTS, 0)); + + + The generator tries to be smart with attributions, but it will work for the + only simplest cases. + + This example + + .. code-block:: c++ + + Py_DECREF(%PYARG_1); + %PYARG_1 = PyInt_FromLong(10); + + + is equivalent of + + .. code-block:: c++ + + Py_DECREF(PyTuple_GET_ITEM(%PYTHON_ARGUMENTS, 0)); + PyTuple_SET_ITEM(%PYTHON_ARGUMENTS, 0, PyInt_FromLong(10)); + .. _pyself: @@ -159,6 +196,16 @@ Variables bounded to the Python wrapper method which receives the custom code. +.. _python_arguments: + +**%PYTHON_ARGUMENTS** + + Replaced by the pointer to the Python tuple with Python objects converted from + the C++ arguments received on the binding override of a virtual method. + This tuple is the same passed as arguments to the Python method overriding the + C++ parent's one. + + .. _pythontypeobject: **%PYTHONTYPEOBJECT** diff --git a/shibokengenerator.cpp b/shibokengenerator.cpp index 8b84d71ec..624c0c2eb 100644 --- a/shibokengenerator.cpp +++ b/shibokengenerator.cpp @@ -864,14 +864,23 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, code.replace(toPythonRegex, "Shiboken::Converter<\\1 >::toPython"); // replace %PYARG_# variables - if (numArgs > 1) { - code.replace(pyArgsRegex, "pyargs[\\1-1]"); + if (snip.language == TypeSystem::TargetLangCode) { + if (numArgs > 1) { + code.replace(pyArgsRegex, "pyargs[\\1-1]"); + } else { + static QRegExp pyArgsRegexCheck("%PYARG_([2-9]+)"); + if (pyArgsRegexCheck.indexIn(code) != -1) + ReportHandler::warning("Wrong index for %PYARG variable ("+pyArgsRegexCheck.cap(1)+") on "+func->signature()); + else + code.replace("%PYARG_1", usePyArgs ? "pyargs[0]" : "arg"); + } } else { - static QRegExp pyArgsRegexCheck("%PYARG_([2-9]+)"); - if (pyArgsRegexCheck.indexIn(code) != -1) - ReportHandler::warning("Wrong index for %PYARG variable ("+pyArgsRegexCheck.cap(1)+") on "+func->signature()); - else - code.replace("%PYARG_1", usePyArgs ? "pyargs[0]" : "arg"); + // Replaces the simplest case of attribution to a Python argument + // on the binding virtual method. + static QRegExp pyArgsAttributionRegex("%PYARG_(\\d+)\\s*=[^=]\\s*([^;]+)"); + code.replace(pyArgsAttributionRegex, "PyTuple_SET_ITEM(pyargs, \\1-1, \\2)"); + + code.replace(pyArgsRegex, "PyTuple_GET_ITEM(pyargs, \\1-1)"); } // replace %ARG#_TYPE variables @@ -892,66 +901,89 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, code.replace("%0", retvalVariableName()); // replace template variable for self Python object - code.replace("%PYSELF", "self"); + QString pySelf; + if (snip.language == TypeSystem::NativeCode) + pySelf = "pySelf"; + else + pySelf = "self"; + code.replace("%PYSELF", pySelf); // replace template variable for pointer to C++ this object if (func->implementingClass()) { - code.replace("%CPPSELF.", "cppSelf->"); - code.replace("%CPPSELF", "cppSelf"); + QString cppSelf; + if (snip.language == TypeSystem::NativeCode) + cppSelf = "this"; + else + cppSelf = "cppSelf"; + code.replace("%CPPSELF.", QString("%1->").arg(cppSelf)); + code.replace("%CPPSELF", cppSelf); // replace template variable for the Python Type object for the // class implementing the method in which the code snip is written if (func->isStatic()) { code.replace("%PYTHONTYPEOBJECT", cpythonTypeName(func->implementingClass())); } else { - code.replace("%PYTHONTYPEOBJECT.", "self->ob_type->"); - code.replace("%PYTHONTYPEOBJECT", "self->ob_type"); + code.replace("%PYTHONTYPEOBJECT.", QString("%1->ob_type->").arg(pySelf)); + code.replace("%PYTHONTYPEOBJECT", QString("%1->ob_type").arg(pySelf)); } } // replace template variables for individual arguments int removed = 0; for (int i = 0; i < func->arguments().size(); i++) { - QString argReplacement; const AbstractMetaArgument* arg = func->arguments().at(i); - if (func->argumentRemoved(i+1)) { - if (!arg->defaultValueExpression().isEmpty()) + QString argReplacement; + if (snip.language == TypeSystem::TargetLangCode) { + if (func->argumentRemoved(i+1)) { + if (!arg->defaultValueExpression().isEmpty()) + argReplacement = arg->defaultValueExpression(); + removed++; + } + + if (lastArg && arg->argumentIndex() > lastArg->argumentIndex()) argReplacement = arg->defaultValueExpression(); - removed++; - } - - if (lastArg && arg->argumentIndex() > lastArg->argumentIndex()) - argReplacement = arg->defaultValueExpression(); - if (argReplacement.isEmpty()) - argReplacement = QString("cpp_arg%1").arg(i - removed); + if (argReplacement.isEmpty()) + argReplacement = QString("cpp_arg%1").arg(i - removed); + } else { + argReplacement = arg->argumentName(); + } code.replace("%" + QString::number(i+1), argReplacement); } - // replace template variables for a list of arguments + // replace template %ARGUMENT_NAMES variable for a list of arguments removed = 0; QStringList argumentNames; foreach (const AbstractMetaArgument* arg, func->arguments()) { - if (func->argumentRemoved(arg->argumentIndex() + 1)) { - if (!arg->defaultValueExpression().isEmpty()) - argumentNames << arg->defaultValueExpression(); - removed++; - continue; - } - - QString argName; - if (lastArg && arg->argumentIndex() > lastArg->argumentIndex()) { - argName = arg->defaultValueExpression(); + if (snip.language == TypeSystem::TargetLangCode) { + if (func->argumentRemoved(arg->argumentIndex() + 1)) { + if (!arg->defaultValueExpression().isEmpty()) + argumentNames << arg->defaultValueExpression(); + removed++; + continue; + } + + QString argName; + if (lastArg && arg->argumentIndex() > lastArg->argumentIndex()) { + argName = arg->defaultValueExpression(); + } else { + argName = QString("cpp_arg%1").arg(arg->argumentIndex() - removed); + if (shouldDereferenceArgumentPointer(arg)) + argName.prepend('*'); + } + argumentNames << argName; } else { - argName = QString("cpp_arg%1").arg(arg->argumentIndex() - removed); - if (shouldDereferenceArgumentPointer(arg)) - argName.prepend('*'); + argumentNames << arg->argumentName(); } - argumentNames << argName; } - code.replace("%ARGUMENT_NAMES", argumentNames.join(", ")); + // replace template %PYTHON_ARGUMENTS variable for a pointer to the Python tuple + // containing the converted virtual method arguments received from C++ to be passed + // to the Python override + if (snip.language == TypeSystem::NativeCode) + code.replace("%PYTHON_ARGUMENTS", "pyargs"); + replaceTemplateVariables(code, func); } |