aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcelo Lira <marcelo.lira@openbossa.org>2009-11-21 23:10:46 -0300
committerMarcelo Lira <marcelo.lira@openbossa.org>2009-11-23 11:48:03 -0300
commite85fcb77b2f1c9db7fbb3008d073609bf710190a (patch)
treea41f1e0deaf917f61e6f96441233feefb38079db
parent8560b8437fdc84f16221cabb37397f092f52e087 (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.rst47
-rw-r--r--shibokengenerator.cpp108
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);
}