diff options
author | Marcelo Lira <marcelo.lira@openbossa.org> | 2010-02-09 15:36:30 -0300 |
---|---|---|
committer | Marcelo Lira <marcelo.lira@openbossa.org> | 2010-02-10 08:43:17 -0300 |
commit | 5316ff58e5c527360d22cd43328990da10ce4ec7 (patch) | |
tree | 560f89928f0905e6c34c247fc0671102d48e14e0 /cppgenerator.cpp | |
parent | e823354fc4e1b5518d47d986bd25b1533637e64f (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.cpp | 38 |
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; + } } } |