aboutsummaryrefslogtreecommitdiffstats
path: root/cppgenerator.cpp
diff options
context:
space:
mode:
authorMarcelo Lira <marcelo.lira@openbossa.org>2010-02-09 15:36:30 -0300
committerMarcelo Lira <marcelo.lira@openbossa.org>2010-02-10 08:43:17 -0300
commit5316ff58e5c527360d22cd43328990da10ce4ec7 (patch)
tree560f89928f0905e6c34c247fc0671102d48e14e0 /cppgenerator.cpp
parente823354fc4e1b5518d47d986bd25b1533637e64f (diff)
Adds support to arguments marked as keep reference in the type system.
Every method marked to increment the reference count of any argument must decrement the reference count of previously held objects. A dictionary is used to associate the method overload and Python wrapper instance with the previously set object.
Diffstat (limited to 'cppgenerator.cpp')
-rw-r--r--cppgenerator.cpp38
1 files changed, 38 insertions, 0 deletions
diff --git a/cppgenerator.cpp b/cppgenerator.cpp
index 543034ed6..49fb4f2ed 100644
--- a/cppgenerator.cpp
+++ b/cppgenerator.cpp
@@ -184,6 +184,18 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl
s << "using namespace Shiboken;" << endl << endl;
+ // If the class has any method with "reference-count" modifications
+ // the support system will need C++ STL's pair and map.
+ if (hasMethodsWithReferenceCountModifications(metaClass)) {
+ s << "#include <map>" << endl;
+ s << "#include <utility>" << endl;
+ s << "using std::make_pair;" << endl;
+ s << "typedef std::pair<PyObject*, const char*> SbkRefCountKey;" << endl;
+ s << "typedef std::map<SbkRefCountKey, PyObject*> SbkRefCountMap;" << endl;
+ s << "static SbkRefCountMap sbk_refcount_map;" << endl;
+ s << endl;
+ }
+
// class inject-code native/beginning
if (!metaClass->typeEntry()->codeSnips().isEmpty()) {
writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), CodeSnip::Beginning, TypeSystem::NativeCode, 0, 0, metaClass);
@@ -1496,10 +1508,14 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f
// Ownership transference between C++ and Python.
QList<ArgumentModification> ownership_mods;
+ // Python object reference management.
+ QList<ArgumentModification> refcount_mods;
foreach (FunctionModification func_mod, func->modifications()) {
foreach (ArgumentModification arg_mod, func_mod.argument_mods) {
if (!arg_mod.ownerships.isEmpty() && arg_mod.ownerships.contains(TypeSystem::TargetLangCode))
ownership_mods.append(arg_mod);
+ else if (!arg_mod.referenceCounts.isEmpty())
+ refcount_mods.append(arg_mod);
}
}
@@ -1527,6 +1543,28 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f
}
s << endl;
}
+
+ } else if (!refcount_mods.isEmpty()) {
+ foreach (ArgumentModification arg_mod, refcount_mods) {
+ if (arg_mod.referenceCounts.first().action != ReferenceCount::Add)
+ continue;
+ const AbstractMetaClass* wrappedClass = 0;
+ QString pyArgName = argumentNameFromIndex(func, arg_mod.index, &wrappedClass);
+ if (!wrappedClass) {
+ s << "#error Invalid reference count modification for argument " << arg_mod.index << endl << endl;
+ break;
+ }
+
+ s << INDENT << "SbkRefCountKey sbk_refcount_key = make_pair(self, \"" << func->minimalSignature() << "\");" << endl;
+ s << INDENT << "SbkRefCountMap::iterator sbk_refcount_iter = sbk_refcount_map.find(sbk_refcount_key);" << endl;
+ s << INDENT << "if (sbk_refcount_iter != sbk_refcount_map.end())" << endl;
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "Py_XDECREF(sbk_refcount_iter->second);" << endl;
+ }
+ s << INDENT << "Py_INCREF(" << pyArgName << ");" << endl;
+ s << INDENT << "sbk_refcount_map[sbk_refcount_key] = " << pyArgName << ';' << endl;
+ }
}
}