From b24af354ea6f05253150179467aa77e7c999611e Mon Sep 17 00:00:00 2001 From: Renato Filho Date: Tue, 20 Apr 2010 19:56:45 -0300 Subject: Fixed argument policy propagate. Reviewer: Hugo Parente Lima , Luciano Wolf --- cppgenerator.cpp | 106 +++++++++++++++------------ cppgenerator.h | 3 +- tests/libsample/objecttype.h | 2 +- tests/libsample/objecttypelayout.h | 2 + tests/samplebinding/objecttypelayout_test.py | 12 ++- 5 files changed, 77 insertions(+), 48 deletions(-) diff --git a/cppgenerator.cpp b/cppgenerator.cpp index 68222adbe..1ec1e44e4 100644 --- a/cppgenerator.cpp +++ b/cppgenerator.cpp @@ -587,16 +587,9 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu writeCodeSnips(s, snips, CodeSnip::End, TypeSystem::NativeCode, func, lastArg); } - // write ownership rules - TypeSystem::Ownership ownership = func->ownership(func->ownerClass(), TypeSystem::TargetLangCode, 0); - if (ownership == TypeSystem::CppOwnership) { - s << INDENT << "// Return value ownership transference" << endl; - s << INDENT << "SbkBaseWrapper_setOwnership("PYTHON_RETURN_VAR".object(), 0);" << endl; - } else - writeReturnValueHeuristics(s, func, "BindingManager::instance().retrieveWrapper(this)"); - if (type) s << INDENT << "return "CPP_RETURN_VAR";" << endl; + s << '}' << endl << endl; } @@ -1606,7 +1599,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f writeCodeSnips(s, snips, CodeSnip::End, TypeSystem::TargetLangCode, func, lastArg); } - writeParentChildManagement(s, func); + bool hasReturnPolicy = false; // Ownership transference between C++ and Python. QList ownership_mods; @@ -1631,6 +1624,9 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f break; } + if (arg_mod.index == 0) + hasReturnPolicy = true; + // The default ownership does nothing. This is useful to avoid automatic heuristically // based generation of code defining parenting. if (arg_mod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::DefaultOwnership) @@ -1665,6 +1661,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f s << func->minimalSignature() << arg_mod.index << "\", " << pyArgName << ");" << endl; } } + writeParentChildManagement(s, func, !hasReturnPolicy); } QStringList CppGenerator::getAncestorMultipleInheritance(const AbstractMetaClass* metaClass) @@ -3067,58 +3064,78 @@ void CppGenerator::finishGeneration() } } -void CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func) +bool CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, int argIndex, bool useHeuristicPolicy) { const int numArgs = func->arguments().count(); const AbstractMetaClass* cppClass = func->ownerClass(); - bool ctorHeuristicEnabled = func->isConstructor() && useCtorHeuristic(); + const AbstractMetaClass* dClass = func->declaringClass(); + bool ctorHeuristicEnabled = func->isConstructor() && useCtorHeuristic() && useHeuristicPolicy; - // -1 = return value - // 0 = self - // 1..n = func. args. - for (int i = -1; i <= numArgs; ++i) { - QString parentVariable; - QString childVariable; - ArgumentOwner argOwner = func->argumentOwner(cppClass, i); - bool usePyArgs = getMinMaxArguments(func).second > 1 || func->isConstructor(); - - ArgumentOwner::Action action = argOwner.action; - int parentIndex = argOwner.index; - int childIndex = i; - if (ctorHeuristicEnabled && i > 0 && numArgs) { - AbstractMetaArgument* arg = func->arguments().at(i-1); - if (arg->argumentName() == "parent" && (arg->type()->isObject() || arg->type()->isQObject())) { - action = ArgumentOwner::Add; - parentIndex = i; - childIndex = -1; - } + QString parentVariable; + QString childVariable; + ArgumentOwner argOwner = func->argumentOwner(cppClass, argIndex); + + if (argOwner.index == -2) //invalid + argOwner = func->argumentOwner(dClass, argIndex); + + bool usePyArgs = getMinMaxArguments(func).second > 1 || func->isConstructor(); + + ArgumentOwner::Action action = argOwner.action; + int parentIndex = argOwner.index; + int childIndex = argIndex; + if (ctorHeuristicEnabled && argIndex > 0 && numArgs) { + AbstractMetaArgument* arg = func->arguments().at(argIndex-1); + if (arg->argumentName() == "parent" && (arg->type()->isObject() || arg->type()->isQObject())) { + action = ArgumentOwner::Add; + parentIndex = argIndex; + childIndex = -1; } + } - if (action != ArgumentOwner::Invalid) { - if (!usePyArgs && i > 1) - ReportHandler::warning("Argument index for parent tag out of bounds: "+func->signature()); + if (action != ArgumentOwner::Invalid) { + if (!usePyArgs && argIndex > 1) + ReportHandler::warning("Argument index for parent tag out of bounds: "+func->signature()); + if (action == ArgumentOwner::Remove) { + parentVariable = "Py_None"; + } else { if (parentIndex == 0) parentVariable = PYTHON_RETURN_VAR; else if (parentIndex == -1) parentVariable = "self"; else parentVariable = usePyArgs ? "pyargs["+QString::number(parentIndex-1)+"]" : "arg"; + } - if (argOwner.action == ArgumentOwner::Remove) - childVariable = "0"; - else if (childIndex == 0) - childVariable = PYTHON_RETURN_VAR; - else if (childIndex == -1) - childVariable = "self"; - else - childVariable = usePyArgs ? "pyargs["+QString::number(childIndex-1)+"]" : "arg"; + if (childIndex == 0) + childVariable = PYTHON_RETURN_VAR; + else if (childIndex == -1) + childVariable = "self"; + else + childVariable = usePyArgs ? "pyargs["+QString::number(childIndex-1)+"]" : "arg"; - s << INDENT << "Shiboken::setParent(" << parentVariable << ", " << childVariable << ");\n"; + s << INDENT << "Shiboken::setParent(" << parentVariable << ", " << childVariable << ");\n"; - } + return true; + } + + if (argIndex == 0 && useHeuristicPolicy) + writeReturnValueHeuristics(s, func); + + return false; +} + +void CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, bool useHeuristicForReturn) +{ + const int numArgs = func->arguments().count(); + s << INDENT << "//CppGenerator::writeParentChildManagement" << endl; + + // -1 = return value + // 0 = self + // 1..n = func. args. + for (int i = -1; i <= numArgs; ++i) { + writeParentChildManagement(s, func, i, i == 0 ? useHeuristicForReturn : true); } - writeReturnValueHeuristics(s, func); } void CppGenerator::writeReturnValueHeuristics(QTextStream& s, const AbstractMetaFunction* func, const QString& self) @@ -3126,7 +3143,6 @@ void CppGenerator::writeReturnValueHeuristics(QTextStream& s, const AbstractMeta AbstractMetaType *type = func->type(); if (!useReturnValueHeuristic() || !func->ownerClass() - || func->ownership(func->ownerClass(), TypeSystem::TargetLangCode, 0) != TypeSystem::InvalidOwnership || !type || func->isStatic() || !func->typeReplaced(0).isEmpty()) { diff --git a/cppgenerator.h b/cppgenerator.h index c9d24d246..b0a9e143e 100644 --- a/cppgenerator.h +++ b/cppgenerator.h @@ -153,7 +153,8 @@ private: void writeExtendedToCppFunction(QTextStream& s, const TypeEntry* externalType, const QList& conversions); void writeExtendedConverterInitialization(QTextStream& s, const TypeEntry* externalType, const QList& conversions); - void writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func); + void writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, bool userHeuristicForReturn); + bool writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, int argIndex, bool userHeuristicPolicy); void writeReturnValueHeuristics(QTextStream& s, const AbstractMetaFunction* func, const QString& self = "self"); /** * Returns the multiple inheritance initializer function for the given class. diff --git a/tests/libsample/objecttype.h b/tests/libsample/objecttype.h index b606dd818..0515ecc98 100644 --- a/tests/libsample/objecttype.h +++ b/tests/libsample/objecttype.h @@ -75,7 +75,7 @@ public: void killChild(const Str& name); void removeChild(ObjectType* child); ObjectType* takeChild(ObjectType* child); - ObjectType* takeChild(const Str& name); + virtual ObjectType* takeChild(const Str& name); ObjectType* findChild(const Str& name); Str objectName() const; diff --git a/tests/libsample/objecttypelayout.h b/tests/libsample/objecttypelayout.h index 5662ac339..1f05b7495 100644 --- a/tests/libsample/objecttypelayout.h +++ b/tests/libsample/objecttypelayout.h @@ -49,6 +49,8 @@ public: virtual bool isLayoutType() { return true; } static ObjectTypeLayout* create() { return new ObjectTypeLayout(); } + + virtual ObjectType* takeChild(const Str& name) { return ObjectType::takeChild(name); } private: std::list m_objects; diff --git a/tests/samplebinding/objecttypelayout_test.py b/tests/samplebinding/objecttypelayout_test.py index 444ee8b5d..1e14e5a4a 100755 --- a/tests/samplebinding/objecttypelayout_test.py +++ b/tests/samplebinding/objecttypelayout_test.py @@ -35,6 +35,17 @@ from sample import * class ObjectTypeLayoutTest(unittest.TestCase): '''Test cases for ObjectTypeLayout class.''' + def testOwnershipOverride(self): + l = ObjectTypeLayout() + + o1 = ObjectType(l) + o1.setObjectName('o1') + + self.assertEqual(sys.getrefcount(o1), 3) + l.takeChild('o1') + self.assertEqual(sys.getrefcount(o1), 2) + + def testSetNullLayout(self): '''ObjectType.setLayout(0).''' o2 = ObjectType() @@ -281,7 +292,6 @@ class ObjectTypeLayoutTest(unittest.TestCase): self.assertRaises(RuntimeError, l1.objectName) self.assertRaises(RuntimeError, l2.objectName) - if __name__ == '__main__': unittest.main() -- cgit v1.2.3