From c3059779d7628fdbb140ed02cdc0cc7ca80e7ad8 Mon Sep 17 00:00:00 2001 From: Kalev Lember Date: Sat, 11 Sep 2010 15:21:58 +0300 Subject: [PATCH 001/564] Fix up shiboken.pc file generation Use @var@ syntax instead of ${var} in shiboken.pc.in; configure_file is called with @ONLY option in CMakeLists.txt, which means that ${var} doesn't get replaced. --- data/shiboken.pc.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/shiboken.pc.in b/data/shiboken.pc.in index ed1cc6c8..c54e84a4 100644 --- a/data/shiboken.pc.in +++ b/data/shiboken.pc.in @@ -7,6 +7,6 @@ generator_location=@CMAKE_INSTALL_PREFIX@/bin/shiboken Name: shiboken Description: Support library for Python bindings created with Shiboken generator. Version: @shiboken_VERSION@ -Libs: -L${libdir} -lpython -lshiboken${shiboken_SUFFIX} -Cflags: -I${includedir}/shiboken${shiboken_SUFFIX} +Libs: -L${libdir} -lpython -lshiboken@shiboken_SUFFIX@ +Cflags: -I${includedir}/shiboken@shiboken_SUFFIX@ From 58692e4b27957b587a9b8bd5075fbcb0daad7998 Mon Sep 17 00:00:00 2001 From: Luciano Wolf Date: Mon, 13 Sep 2010 16:16:40 -0300 Subject: [PATCH 002/564] Fix code generation for modified constructors. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewers: Renato Araújo Hugo Parente Lima --- headergenerator.cpp | 10 +++-- tests/libsample/CMakeLists.txt | 1 + tests/libsample/modified_constructor.cpp | 36 +++++++++++++++ tests/libsample/modified_constructor.h | 40 +++++++++++++++++ tests/samplebinding/CMakeLists.txt | 1 + tests/samplebinding/global.h | 1 + .../modified_constructor_test.py | 44 +++++++++++++++++++ tests/samplebinding/typesystem_sample.xml | 11 +++++ 8 files changed, 140 insertions(+), 4 deletions(-) create mode 100644 tests/libsample/modified_constructor.cpp create mode 100644 tests/libsample/modified_constructor.h create mode 100644 tests/samplebinding/modified_constructor_test.py diff --git a/headergenerator.cpp b/headergenerator.cpp index 59028081..90c27b81 100644 --- a/headergenerator.cpp +++ b/headergenerator.cpp @@ -186,11 +186,13 @@ void HeaderGenerator::writeFunction(QTextStream& s, const AbstractMetaFunction* if (func->isConstructor() || func->isAbstract() || func->isVirtual()) { s << INDENT; - Options virtualOption = Generator::NoOption; - if (func->isVirtual() || func->isAbstract()) { - virtualOption = Generator::OriginalTypeDescription; + Options virtualOption = Generator::OriginalTypeDescription; + + if (func->isVirtual() || func->isAbstract()) s << "virtual "; - } + else if (!func->hasSignatureModifications()) + virtualOption = Generator::NoOption; + s << functionSignature(func, "", "", virtualOption) << ';' << endl; // TODO: when modified an abstract method ceases to be virtual but stays abstract diff --git a/tests/libsample/CMakeLists.txt b/tests/libsample/CMakeLists.txt index c1386bf1..d7bede64 100644 --- a/tests/libsample/CMakeLists.txt +++ b/tests/libsample/CMakeLists.txt @@ -14,6 +14,7 @@ injectcode.cpp listuser.cpp modifications.cpp mapuser.cpp +modified_constructor.cpp multiple_derived.cpp objecttype.cpp objecttypelayout.cpp diff --git a/tests/libsample/modified_constructor.cpp b/tests/libsample/modified_constructor.cpp new file mode 100644 index 00000000..952ae7b4 --- /dev/null +++ b/tests/libsample/modified_constructor.cpp @@ -0,0 +1,36 @@ +/* + * This file is part of the Shiboken Python Binding Generator project. + * + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "modified_constructor.h" + +ModifiedConstructor::ModifiedConstructor(int first_arg) +{ + m_stored_value = first_arg; +} + +int +ModifiedConstructor::retrieveValue() +{ + return m_stored_value; +} + + diff --git a/tests/libsample/modified_constructor.h b/tests/libsample/modified_constructor.h new file mode 100644 index 00000000..242b1d5a --- /dev/null +++ b/tests/libsample/modified_constructor.h @@ -0,0 +1,40 @@ +/* + * This file is part of the Shiboken Python Binding Generator project. + * + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MODIFIEDCONSTRUCTOR_H +#define MODIFIEDCONSTRUCTOR_H + +#include "libsamplemacros.h" + +class LIBSAMPLE_API ModifiedConstructor +{ +public: + + ModifiedConstructor(int first_arg); + int retrieveValue(); + +private: + int m_stored_value; +}; + +#endif // MODIFIEDCONSTRUCTOR_H + diff --git a/tests/samplebinding/CMakeLists.txt b/tests/samplebinding/CMakeLists.txt index 14ec6693..3536ce39 100644 --- a/tests/samplebinding/CMakeLists.txt +++ b/tests/samplebinding/CMakeLists.txt @@ -35,6 +35,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/mderived3_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/mderived4_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/mderived5_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/modifications_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/modifiedconstructor_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/noimplicitconversion_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/nondefaultctor_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/objecttype_wrapper.cpp diff --git a/tests/samplebinding/global.h b/tests/samplebinding/global.h index f7933536..2e06bce5 100644 --- a/tests/samplebinding/global.h +++ b/tests/samplebinding/global.h @@ -13,6 +13,7 @@ #include "listuser.h" #include "mapuser.h" #include "modifications.h" +#include "modified_constructor.h" #include "multiple_derived.h" #include "noimplicitconversion.h" #include "nondefaultctor.h" diff --git a/tests/samplebinding/modified_constructor_test.py b/tests/samplebinding/modified_constructor_test.py new file mode 100644 index 00000000..80612bd8 --- /dev/null +++ b/tests/samplebinding/modified_constructor_test.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# This file is part of the Shiboken Python Bindings Generator project. +# +# Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +# +# Contact: PySide team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# version 2.1 as published by the Free Software Foundation. Please +# review the following information to ensure the GNU Lesser General +# Public License version 2.1 requirements will be met: +# http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +# # +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +'''Tests cases for ConstructorWithModifiedArgument class.''' + +import sys +import unittest + +from sample import * + + +class ConstructorWithModifiedArgumentTest(unittest.TestCase): + '''Test cases for ConstructorWithModifiedArgument class.''' + + def testConstructorWithModifiedArgument(self): + sampleClass = ModifiedConstructor("10") + self.assertTrue(sampleClass.retrieveValue(), 10) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 7b02a4d3..de262c9e 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -123,6 +123,17 @@ + + + + + + + %0 = new %FUNCTION_NAME(atoi(%CONVERTTOCPP[const char *](%PYARG_1))); + + + + From aa1b98fa000f90b9905fcb4a1f1eccefd3851105 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Tue, 14 Sep 2010 18:33:21 -0300 Subject: [PATCH 003/564] Generate correct python function definitions. Reviewer: Hugo Parente Lima Luciano Wolf --- cppgenerator.cpp | 32 ++++++++++++-------------------- cppgenerator.h | 3 --- overloaddata.h | 2 +- shibokengenerator.cpp | 16 ++++++++++++++-- shibokengenerator.h | 5 +++++ 5 files changed, 32 insertions(+), 26 deletions(-) diff --git a/cppgenerator.cpp b/cppgenerator.cpp index 507ef7f2..f264a1ea 100644 --- a/cppgenerator.cpp +++ b/cppgenerator.cpp @@ -473,7 +473,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu if (func->isAbstract()) { s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '"; s << func->ownerClass()->name() << '.' << func->name(); - s << "()' not implemented.\");" << endl; + s << "()' not implemented.\");" << endl; s << INDENT << "return "; if (func->type()) { writeMinimalConstructorCallArguments(s, func->type()); @@ -1230,7 +1230,7 @@ void CppGenerator::writeArgumentsInitializer(QTextStream& s, OverloadData& overl QStringList palist; s << INDENT << "PyObject* "; - if (maxArgs == 1) { + if (!pythonFunctionWrapperUsesListOfArguments(overloadData)) { s << "arg = 0"; palist << "&arg"; } else { @@ -1343,7 +1343,7 @@ void CppGenerator::writeErrorSection(QTextStream& s, OverloadData& overloadData) Indentation indentation(INDENT); QString funcName = fullPythonFunctionName(rfunc); - QString argsVar = !rfunc->isConstructor() && overloadData.maxArgs() == 1 ? "arg" : "args"; + QString argsVar = pythonFunctionWrapperUsesListOfArguments(overloadData) ? "args" : "arg";; if (verboseErrorMessagesDisabled()) { s << INDENT << "Shiboken::setErrorAboutWrongArguments(" << argsVar << ", \"" << funcName << "\", 0);" << endl; } else { @@ -1640,7 +1640,7 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream& s, const Ov int startArg = od->argPos(); int sequenceArgCount = 0; while (od && !od->argType()->isVarargs()) { - if (usePyArgs && maxArgs > 1) + if (usePyArgs) pyArgName = QString("pyargs[%1]").arg(od->argPos()); writeTypeCheck(tck, od, pyArgName); @@ -1728,7 +1728,7 @@ void CppGenerator::writeSingleFunctionCall(QTextStream& s, const OverloadData& o const AbstractMetaClass* implementingClass = overloadData.referenceFunction()->implementingClass(); - bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(overloadData) && overloadData.maxArgs() > 1; + bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(overloadData); // Handle named arguments. writeNamedArgumentResolution(s, func, usePyArgs); @@ -2317,14 +2317,6 @@ bool CppGenerator::shouldGenerateGetSetList(const AbstractMetaClass* metaClass) return false; } -bool CppGenerator::pythonFunctionWrapperUsesListOfArguments(const OverloadData& overloadData) -{ - bool usePyArgs = overloadData.maxArgs() > 1 - || overloadData.referenceFunction()->isConstructor() - || overloadData.hasArgumentWithDefaultValue(); - return usePyArgs; -} - void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* metaClass) { QString tp_flags; @@ -2855,14 +2847,14 @@ void CppGenerator::writeMethodDefinitionEntry(QTextStream& s, const AbstractMeta OverloadData overloadData(overloads, this); bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(overloadData); const AbstractMetaFunction* func = overloadData.referenceFunction(); + int min = overloadData.minArgs(); + int max = overloadData.maxArgs(); s << '"' << func->name() << "\", (PyCFunction)" << cpythonFunctionName(func) << ", "; - if (overloadData.maxArgs() < 2 && !usePyArgs) { - bool minZero = overloadData.minArgs() == 0; - bool maxOne = overloadData.maxArgs() == 1; - if (minZero) - s << "METH_NOARGS" << (maxOne ? "|" : ""); - if (maxOne) + if ((min == max) && (max < 2) && !usePyArgs) { + if (max == 0) + s << "METH_NOARGS"; + else s << "METH_O"; } else { s << "METH_VARARGS"; @@ -3738,7 +3730,7 @@ bool CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMeta if (argOwner.index == -2) //invalid argOwner = func->argumentOwner(dClass, argIndex); - bool usePyArgs = OverloadData(getFunctionGroups(func->implementingClass())[func->name()], this).maxArgs() > 1; + bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(OverloadData(getFunctionGroups(func->implementingClass())[func->name()], this)); ArgumentOwner::Action action = argOwner.action; int parentIndex = argOwner.index; diff --git a/cppgenerator.h b/cppgenerator.h index 7ce84935..1d2d122c 100644 --- a/cppgenerator.h +++ b/cppgenerator.h @@ -186,9 +186,6 @@ class CppGenerator : public ShibokenGenerator /// Returns true if generator should produce getters and setters for the given class. bool shouldGenerateGetSetList(const AbstractMetaClass* metaClass); - /// Returns true if the Python wrapper for the received OverloadData must accept a list of arguments. - static bool pythonFunctionWrapperUsesListOfArguments(const OverloadData& overloadData); - void writeHashFunction(QTextStream& s, const AbstractMetaClass* metaClass); void writeObjCopierFunction(QTextStream& s, const AbstractMetaClass* metaClass); diff --git a/overloaddata.h b/overloaddata.h index 3e5d0cc6..a0bd4640 100644 --- a/overloaddata.h +++ b/overloaddata.h @@ -28,7 +28,7 @@ #include #include -#include "shibokengenerator.h" +class ShibokenGenerator; class OverloadData; typedef QList OverloadDataList; diff --git a/shibokengenerator.cpp b/shibokengenerator.cpp index b6edd6a3..e7d0b7de 100644 --- a/shibokengenerator.cpp +++ b/shibokengenerator.cpp @@ -1087,7 +1087,7 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, argsRemoved++; } numArgs = func->arguments().size() - argsRemoved; - usePyArgs = getMinMaxArguments(func).second > 1; + usePyArgs = pythonFunctionWrapperUsesListOfArguments(OverloadData(getFunctionGroups(func->implementingClass())[func->name()], this)); } foreach (CodeSnip snip, codeSnips) { @@ -1114,7 +1114,7 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, // replace %PYARG_# variables code.replace("%PYARG_0", PYTHON_RETURN_VAR); if (snip.language == TypeSystem::TargetLangCode) { - if (numArgs > 1) { + if (usePyArgs) { code.replace(pyArgsRegex, "pyargs[\\1-1]"); } else { static QRegExp pyArgsRegexCheck("%PYARG_([2-9]+)"); @@ -1637,3 +1637,15 @@ bool ShibokenGenerator::verboseErrorMessagesDisabled() const return m_verboseErrorMessagesDisabled; } + +bool ShibokenGenerator::pythonFunctionWrapperUsesListOfArguments(const OverloadData& overloadData) +{ + int maxArgs = overloadData.maxArgs(); + int minArgs = overloadData.minArgs(); + bool usePyArgs = (minArgs != maxArgs) + || (maxArgs > 1) + || overloadData.referenceFunction()->isConstructor() + || overloadData.hasArgumentWithDefaultValue(); + return usePyArgs; +} + diff --git a/shibokengenerator.h b/shibokengenerator.h index 37f484a9..1a7c5a63 100644 --- a/shibokengenerator.h +++ b/shibokengenerator.h @@ -32,6 +32,8 @@ #include #include +#include "overloaddata.h" + class DocParser; /** @@ -346,6 +348,9 @@ class ShibokenGenerator : public Generator /// Returns all extended conversions for the current module. ExtendedConverterData getExtendedConverters() const; + /// Returns true if the Python wrapper for the received OverloadData must accept a list of arguments. + static bool pythonFunctionWrapperUsesListOfArguments(const OverloadData& overloadData); + Indentor INDENT; private: bool m_useCtorHeuristic; From c793ffb0f0719dcd220f277f9fc0c464a19f9f0a Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 15 Sep 2010 10:52:54 -0300 Subject: [PATCH 004/564] Fix bug#347 - "Setting properties in constructors gives incorrect results" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Luciano Wolf Renato Araújo --- cppgenerator.cpp | 139 ++++++++++++----------------------------------- cppgenerator.h | 1 - 2 files changed, 36 insertions(+), 104 deletions(-) diff --git a/cppgenerator.cpp b/cppgenerator.cpp index f264a1ea..a37ea414 100644 --- a/cppgenerator.cpp +++ b/cppgenerator.cpp @@ -756,6 +756,26 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun if (needsOverloadId) s << INDENT << "int overloadId = -1;" << endl; + QSet argNamesSet; + if (usePySideExtensions() && metaClass->isQObject()) { + // Write argNames variable with all known argument names. + foreach (const AbstractMetaFunction* func, overloadData.overloads()) { + foreach (const AbstractMetaArgument* arg, func->arguments()) { + if (arg->defaultValueExpression().isEmpty() || func->argumentRemoved(arg->argumentIndex() + 1)) + continue; + argNamesSet << arg->name(); + } + } + QStringList argNamesList = argNamesSet.toList(); + qSort(argNamesList.begin(), argNamesList.end()); + if (argNamesList.isEmpty()) + s << INDENT << "const char** argNames = 0;" << endl; + else + s << INDENT << "const char* argNames[] = {\"" << argNamesList.join("\", \"") << "\"};" << endl; + s << INDENT << "const QMetaObject* metaObject;" << endl; + } + + s << INDENT << "SbkBaseWrapper* sbkSelf = reinterpret_cast(self);" << endl; if (metaClass->isAbstract() || metaClass->baseClassNames().size() > 1) { @@ -794,12 +814,8 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun s << endl; - if (metaClass->isQObject() || overloadData.hasArgumentWithDefaultValue()) { - // Check usage of unknown named arguments - writeNamedArgumentsCheck(s, overloadData); - if (!metaClass->isQObject()) - s << INDENT << "int numNamedArgs = (kwds ? PyDict_Size(kwds) : 0);" << endl; - } + if (!metaClass->isQObject() && overloadData.hasArgumentWithDefaultValue()) + s << INDENT << "int numNamedArgs = (kwds ? PyDict_Size(kwds) : 0);" << endl; if (overloadData.maxArgs() > 0) { s << endl << INDENT << "int numArgs = "; writeArgumentsInitializer(s, overloadData); @@ -833,46 +849,14 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun s << INDENT << "BindingManager::instance().registerWrapper(sbkSelf, cptr);" << endl; // Create metaObject and register signal/slot - if (metaClass->isQObject()) { - if (usePySideExtensions()) - s << INDENT << "PySide::signalUpdateSource(self);" << endl; - - s << INDENT << "cptr->metaObject();" << endl; - - if (metaClass->isQObject()) { - s << INDENT << "for (std::vector::size_type i = 0; i < propertyKeys.size(); i++) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "const char* propName = PyString_AS_STRING(propertyKeys[i]);" << endl; - s << INDENT << "const QMetaObject* mo = cptr->metaObject();" << endl; - s << INDENT << "if (mo->indexOfProperty(propName) != -1) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "cptr->setProperty(propName, "; - s << "Shiboken::Converter::toCpp(PyDict_GetItem(kwds, propertyKeys[i])));" << endl; - } - s << INDENT << "} else {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "QString signalSignature = QString(\"%1()\").arg(propName);" << endl; - s << INDENT << "if (mo->indexOfSignal(qPrintable(signalSignature)) != -1) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "signalSignature = '2' + signalSignature;" << endl; - s << INDENT << "PySide::signal_connect(self, qPrintable(signalSignature), PyDict_GetItem(kwds, propertyKeys[i]));" << endl; - } - s << INDENT << "} else {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "delete cptr;" << endl; - s << INDENT << "PyErr_Format(PyExc_AttributeError, \"'%s' is not a Qt property or a signal\", propName);" << endl; - s << INDENT << "return -1;" << endl; - } - s << INDENT << "};" << endl; - } - s << INDENT << "}" << endl; - } - s << INDENT << '}' << endl; + if (metaClass->isQObject() && usePySideExtensions()) { + s << endl << INDENT << "// QObject setup" << endl; + s << INDENT << "PySide::signalUpdateSource(self);" << endl; + s << INDENT << "metaObject = cptr->metaObject(); // <- init python qt properties" << endl; + s << INDENT << "if (kwds && !PySide::fillQtProperties(self, metaObject, kwds, argNames, " << argNamesSet.count() << "))" << endl; + { + Indentation indentation(INDENT); + s << INDENT << "return " << m_currentErrorCode << ';' << endl; } } @@ -1067,8 +1051,6 @@ void CppGenerator::writeMethodWrapper(QTextStream& s, const AbstractMetaFunction s << INDENT << "int overloadId = -1;" << endl; if (usesNamedArguments) { - // Check usage of unknown named arguments - writeNamedArgumentsCheck(s, overloadData); s << INDENT << "int numNamedArgs = (kwds ? PyDict_Size(kwds) : 0);" << endl; } @@ -1165,60 +1147,6 @@ void CppGenerator::writeMethodWrapper(QTextStream& s, const AbstractMetaFunction s << '}' << endl << endl; } -void CppGenerator::writeNamedArgumentsCheck(QTextStream& s, OverloadData& overloadData) -{ - // Check usage of unknown named arguments - QSet argNamesSet; - foreach (const AbstractMetaFunction* func, overloadData.overloads()) { - foreach (const AbstractMetaArgument* arg, func->arguments()) { - if (arg->defaultValueExpression().isEmpty() - || func->argumentRemoved(arg->argumentIndex() + 1)) - continue; - argNamesSet << QString("\"%1\"").arg(arg->name()); - } - } - QStringList argNamesList = argNamesSet.toList(); - qSort(argNamesList.begin(), argNamesList.end()); - - const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); - bool ownerClassIsQObject = rfunc->ownerClass() && rfunc->ownerClass()->isQObject() && rfunc->isConstructor(); - if (overloadData.hasArgumentWithDefaultValue() || (ownerClassIsQObject && rfunc->isConstructor())) { - s << INDENT << "std::vector propertyKeys;" << endl << endl; - s << INDENT << "// Check existence of named argument." << endl; - s << INDENT << "if (kwds) {" << endl; - { - Indentation indent(INDENT); - if (argNamesList.size() > 0) - s << INDENT << "std::string argNames[] = { " << argNamesList.join(", ") << " };" << endl; - s << INDENT << "PyObject* keys = PyDict_Keys(kwds);" << endl; - s << INDENT << "Shiboken::AutoDecRef auto_keys(keys);" << endl; - s << INDENT << "for (int i = 0; i < PyList_GET_SIZE(keys); ++i) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyObject* argName = PyList_GET_ITEM(keys, i);" << endl; - if (argNamesList.size() > 0) { - s << INDENT << "if (!std::binary_search(argNames, argNames + " << argNamesList.count(); - s << ", std::string(PyString_AS_STRING(argName)))) {" << endl; - } - { - Indentation indent(INDENT); - if (ownerClassIsQObject) { - s << INDENT << "propertyKeys.push_back(argName);" << endl; - } else { - s << INDENT << "PyErr_Format(PyExc_TypeError, \"" << fullPythonFunctionName(overloadData.referenceFunction()); - s << "(): got an unexpected keyword argument '%s'\", PyString_AS_STRING(argName));" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - } - if (argNamesList.size() > 0) - s << INDENT << '}' << endl; - } - s << INDENT << '}' << endl; - } - } - s << INDENT << '}' << endl; -} - void CppGenerator::writeArgumentsInitializer(QTextStream& s, OverloadData& overloadData) { const AbstractMetaFunction* rfunc = overloadData.referenceFunction(); @@ -3471,11 +3399,16 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, const AbstractMetaClass s << INDENT << '}' << endl; } s << INDENT << "PyObject* attr = PyObject_GenericGetAttr(self, name);" << endl; - if (usePySideExtensions()) { + if (usePySideExtensions() && metaClass->isQObject()) { s << INDENT << "if (attr && PySide::isQPropertyType(attr)) {" << endl; { Indentation indent(INDENT); s << INDENT << "PyObject *value = PySide::qproperty_get(attr, self);" << endl; + s << INDENT << "if (!value)" << endl; + { + Indentation indentation(INDENT); + s << INDENT << "return " << m_currentErrorCode << ';' << endl; + } s << INDENT << "Py_DECREF(attr);" << endl; s << INDENT << "Py_INCREF(value);" << endl; s << INDENT << "attr = value;" << endl; diff --git a/cppgenerator.h b/cppgenerator.h index 1d2d122c..b4d68dc4 100644 --- a/cppgenerator.h +++ b/cppgenerator.h @@ -53,7 +53,6 @@ class CppGenerator : public ShibokenGenerator void writeMinimalConstructorCallArguments(QTextStream& s, const AbstractMetaType* type); void writeMethodWrapper(QTextStream &s, const AbstractMetaFunctionList overloads); void writeArgumentsInitializer(QTextStream& s, OverloadData& overloadData); - void writeNamedArgumentsCheck(QTextStream& s, OverloadData& overloadData); void writeCppSelfDefinition(QTextStream& s, const AbstractMetaFunction* func); void writeErrorSection(QTextStream& s, OverloadData& overloadData); From 039712dfe1bbcbc2af4c831824f206c81d9de9ca Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 15 Sep 2010 15:13:56 -0300 Subject: [PATCH 005/564] Version bump --- CMakeLists.txt | 2 +- doc/conf.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f72ef81..ab604af9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -53,7 +53,7 @@ set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The s set(shiboken_MAJOR_VERSION "0") set(shiboken_MINOR_VERSION "5") -set(shiboken_MICRO_VERSION "0") +set(shiboken_MICRO_VERSION "1") set(shiboken_VERSION "${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VERSION}.${shiboken_MICRO_VERSION}") if(ENABLE_VERSION_SUFFIX) set(shiboken_SUFFIX "-${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VERSION}") diff --git a/doc/conf.py b/doc/conf.py index f7ea16e7..4468df70 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -49,9 +49,9 @@ # built documents. # # The short X.Y version. -version = '0.3' +version = '0.5' # The full version, including alpha/beta/rc tags. -release = '0.3.1' +release = '0.5.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. From 56eb6c1f44682f10a7ddc041bcbe0424a552e5c3 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 15 Sep 2010 15:14:19 -0300 Subject: [PATCH 006/564] Fixed broken sphinx syntax. --- doc/codeinjectionsemantics.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/codeinjectionsemantics.rst b/doc/codeinjectionsemantics.rst index 872662ad..d748a3aa 100644 --- a/doc/codeinjectionsemantics.rst +++ b/doc/codeinjectionsemantics.rst @@ -65,7 +65,7 @@ The following table describes the semantics of ``inject-code`` tag as used on | | | |initializer function (``init_CLASS(PyObject *module)``). The | | | | |code here will be executed after all the wrapped class | | | | |components have been initialized. | - +---------------+------+---------+--------------------------------------------------------------+ + +---------------+------+---------+--------------------------------------------------------------+ |modify-function|native|beginning|Code here is put on the virtual method override of a C++ | | | | |wrapper class (the one responsible for passing C++ calls to a | | | | |Python override, if there is any), right after the C++ | From e792b618ecf6a6bb19046e4faf4b30dcd01794e7 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 15 Sep 2010 15:14:50 -0300 Subject: [PATCH 007/564] Fixed minor cosmetic issues in the generated code. --- cppgenerator.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cppgenerator.cpp b/cppgenerator.cpp index a37ea414..89efd3b3 100644 --- a/cppgenerator.cpp +++ b/cppgenerator.cpp @@ -134,8 +134,6 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl // headers s << "// default includes" << endl; s << "#include " << endl; - s << "#include " << endl; - s << "#include " << endl; if (usePySideExtensions()) { s << "#include " << endl; s << "#include " << endl; @@ -1641,8 +1639,9 @@ void CppGenerator::writeFunctionCalls(QTextStream& s, const OverloadData& overlo } } } - s << INDENT << '}' << endl << INDENT << "}"; + s << INDENT << '}' << endl; } + s << INDENT << '}' << endl; } void CppGenerator::writeSingleFunctionCall(QTextStream& s, const OverloadData& overloadData, const AbstractMetaFunction* func) @@ -1653,8 +1652,6 @@ void CppGenerator::writeSingleFunctionCall(QTextStream& s, const OverloadData& o return; } - - const AbstractMetaClass* implementingClass = overloadData.referenceFunction()->implementingClass(); bool usePyArgs = pythonFunctionWrapperUsesListOfArguments(overloadData); @@ -1698,9 +1695,12 @@ void CppGenerator::writeSingleFunctionCall(QTextStream& s, const OverloadData& o int numRemovedArgs = OverloadData::numberOfRemovedArguments(func); s << INDENT << "if(!PyErr_Occurred()) {" << endl; - writeMethodCall(s, func, func->arguments().size() - numRemovedArgs); - if (!func->isConstructor()) - writeNoneReturn(s, func, overloadData.hasNonVoidReturnType()); + { + Indentation indentation(INDENT); + writeMethodCall(s, func, func->arguments().size() - numRemovedArgs); + if (!func->isConstructor()) + writeNoneReturn(s, func, overloadData.hasNonVoidReturnType()); + } s << INDENT << "}" << endl; } From 54ef77809639c5d4599539b9939f28dbd3599513 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 15 Sep 2010 15:15:25 -0300 Subject: [PATCH 008/564] Fixed copyright year in the generated docs. --- doc/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/conf.py b/doc/conf.py index 4468df70..21091828 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -42,7 +42,7 @@ # General information about the project. project = u'Shiboken' -copyright = u'2009, Nokia Corporation' +copyright = u'2009-2010, Nokia Corporation' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the From fc0202caa9b0f072ae7185e40555df1a61c9b4ea Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 15 Sep 2010 16:18:09 -0300 Subject: [PATCH 009/564] Removed outdated and broke Doxygen configuration file. --- Doxyfile | 311 ------------------------------------------------------- 1 file changed, 311 deletions(-) delete mode 100644 Doxyfile diff --git a/Doxyfile b/Doxyfile deleted file mode 100644 index 24289839..00000000 --- a/Doxyfile +++ /dev/null @@ -1,311 +0,0 @@ -# Doxyfile 1.5.7.1 - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -DOXYFILE_ENCODING = UTF-8 -PROJECT_NAME = "CPython Generator Backend" -PROJECT_NUMBER = 0.1 -OUTPUT_DIRECTORY = doc -CREATE_SUBDIRS = NO -OUTPUT_LANGUAGE = English -BRIEF_MEMBER_DESC = YES -REPEAT_BRIEF = YES -ABBREVIATE_BRIEF = "The $name class" \ - "The $name widget" \ - "The $name file" \ - is \ - provides \ - specifies \ - contains \ - represents \ - a \ - an \ - the -ALWAYS_DETAILED_SEC = NO -INLINE_INHERITED_MEMB = NO -FULL_PATH_NAMES = YES -STRIP_FROM_PATH = /tmp/src/cpythonbackend/ -STRIP_FROM_INC_PATH = -SHORT_NAMES = NO -JAVADOC_AUTOBRIEF = YES -QT_AUTOBRIEF = NO -MULTILINE_CPP_IS_BRIEF = NO -INHERIT_DOCS = YES -SEPARATE_MEMBER_PAGES = NO -TAB_SIZE = 8 -ALIASES = -OPTIMIZE_OUTPUT_FOR_C = NO -OPTIMIZE_OUTPUT_JAVA = NO -OPTIMIZE_FOR_FORTRAN = NO -OPTIMIZE_OUTPUT_VHDL = NO -BUILTIN_STL_SUPPORT = NO -CPP_CLI_SUPPORT = NO -SIP_SUPPORT = NO -IDL_PROPERTY_SUPPORT = YES -DISTRIBUTE_GROUP_DOC = NO -SUBGROUPING = YES -TYPEDEF_HIDES_STRUCT = NO -SYMBOL_CACHE_SIZE = 0 -#--------------------------------------------------------------------------- -# Build related configuration options -#--------------------------------------------------------------------------- -EXTRACT_ALL = YES -EXTRACT_PRIVATE = YES -EXTRACT_STATIC = YES -EXTRACT_LOCAL_CLASSES = YES -EXTRACT_LOCAL_METHODS = NO -EXTRACT_ANON_NSPACES = NO -HIDE_UNDOC_MEMBERS = NO -HIDE_UNDOC_CLASSES = NO -HIDE_FRIEND_COMPOUNDS = NO -HIDE_IN_BODY_DOCS = NO -INTERNAL_DOCS = NO -CASE_SENSE_NAMES = YES -HIDE_SCOPE_NAMES = NO -SHOW_INCLUDE_FILES = YES -INLINE_INFO = YES -SORT_MEMBER_DOCS = YES -SORT_BRIEF_DOCS = NO -SORT_GROUP_NAMES = NO -SORT_BY_SCOPE_NAME = NO -GENERATE_TODOLIST = YES -GENERATE_TESTLIST = YES -GENERATE_BUGLIST = YES -GENERATE_DEPRECATEDLIST= YES -ENABLED_SECTIONS = -MAX_INITIALIZER_LINES = 30 -SHOW_USED_FILES = YES -SHOW_DIRECTORIES = NO -SHOW_FILES = YES -SHOW_NAMESPACES = YES -FILE_VERSION_FILTER = -LAYOUT_FILE = -#--------------------------------------------------------------------------- -# configuration options related to warning and progress messages -#--------------------------------------------------------------------------- -QUIET = NO -WARNINGS = YES -WARN_IF_UNDOCUMENTED = YES -WARN_IF_DOC_ERROR = YES -WARN_NO_PARAMDOC = NO -WARN_FORMAT = "$file:$line: $text" -WARN_LOGFILE = -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = /tmp/src/cpythonbackend -INPUT_ENCODING = UTF-8 -FILE_PATTERNS = *.c \ - *.cc \ - *.cxx \ - *.cpp \ - *.c++ \ - *.d \ - *.java \ - *.ii \ - *.ixx \ - *.ipp \ - *.i++ \ - *.inl \ - *.h \ - *.hh \ - *.hxx \ - *.hpp \ - *.h++ \ - *.idl \ - *.odl \ - *.cs \ - *.php \ - *.php3 \ - *.inc \ - *.m \ - *.mm \ - *.dox \ - *.py \ - *.f90 \ - *.f \ - *.vhd \ - *.vhdl \ - *.C \ - *.CC \ - *.C++ \ - *.II \ - *.I++ \ - *.H \ - *.HH \ - *.H++ \ - *.CS \ - *.PHP \ - *.PHP3 \ - *.M \ - *.MM \ - *.PY \ - *.F90 \ - *.F \ - *.VHD \ - *.VHDL -RECURSIVE = YES -EXCLUDE = -EXCLUDE_SYMLINKS = NO -EXCLUDE_PATTERNS = -EXCLUDE_SYMBOLS = -EXAMPLE_PATH = -EXAMPLE_PATTERNS = * -EXAMPLE_RECURSIVE = NO -IMAGE_PATH = -INPUT_FILTER = -FILTER_PATTERNS = -FILTER_SOURCE_FILES = NO -#--------------------------------------------------------------------------- -# configuration options related to source browsing -#--------------------------------------------------------------------------- -SOURCE_BROWSER = NO -INLINE_SOURCES = NO -STRIP_CODE_COMMENTS = YES -REFERENCED_BY_RELATION = NO -REFERENCES_RELATION = NO -REFERENCES_LINK_SOURCE = YES -USE_HTAGS = NO -VERBATIM_HEADERS = NO -#--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index -#--------------------------------------------------------------------------- -ALPHABETICAL_INDEX = YES -COLS_IN_ALPHA_INDEX = 3 -IGNORE_PREFIX = -#--------------------------------------------------------------------------- -# configuration options related to the HTML output -#--------------------------------------------------------------------------- -GENERATE_HTML = YES -HTML_OUTPUT = html -HTML_FILE_EXTENSION = .html -HTML_HEADER = -HTML_FOOTER = -HTML_STYLESHEET = -HTML_ALIGN_MEMBERS = YES -HTML_DYNAMIC_SECTIONS = NO -GENERATE_DOCSET = NO -DOCSET_FEEDNAME = "Doxygen generated docs" -DOCSET_BUNDLE_ID = org.doxygen.Project -GENERATE_HTMLHELP = NO -CHM_FILE = -HHC_LOCATION = -GENERATE_CHI = NO -CHM_INDEX_ENCODING = -BINARY_TOC = NO -TOC_EXPAND = NO -GENERATE_QHP = NO -QCH_FILE = -QHP_NAMESPACE = org.doxygen.Project -QHP_VIRTUAL_FOLDER = doc -QHG_LOCATION = -DISABLE_INDEX = NO -ENUM_VALUES_PER_LINE = 4 -GENERATE_TREEVIEW = NONE -TREEVIEW_WIDTH = 250 -FORMULA_FONTSIZE = 10 -#--------------------------------------------------------------------------- -# configuration options related to the LaTeX output -#--------------------------------------------------------------------------- -GENERATE_LATEX = NO -LATEX_OUTPUT = latex -LATEX_CMD_NAME = latex -MAKEINDEX_CMD_NAME = makeindex -COMPACT_LATEX = NO -PAPER_TYPE = a4wide -EXTRA_PACKAGES = -LATEX_HEADER = -PDF_HYPERLINKS = YES -USE_PDFLATEX = YES -LATEX_BATCHMODE = NO -LATEX_HIDE_INDICES = NO -#--------------------------------------------------------------------------- -# configuration options related to the RTF output -#--------------------------------------------------------------------------- -GENERATE_RTF = NO -RTF_OUTPUT = rtf -COMPACT_RTF = NO -RTF_HYPERLINKS = NO -RTF_STYLESHEET_FILE = -RTF_EXTENSIONS_FILE = -#--------------------------------------------------------------------------- -# configuration options related to the man page output -#--------------------------------------------------------------------------- -GENERATE_MAN = NO -MAN_OUTPUT = man -MAN_EXTENSION = .3 -MAN_LINKS = NO -#--------------------------------------------------------------------------- -# configuration options related to the XML output -#--------------------------------------------------------------------------- -GENERATE_XML = NO -XML_OUTPUT = xml -XML_SCHEMA = -XML_DTD = -XML_PROGRAMLISTING = YES -#--------------------------------------------------------------------------- -# configuration options for the AutoGen Definitions output -#--------------------------------------------------------------------------- -GENERATE_AUTOGEN_DEF = NO -#--------------------------------------------------------------------------- -# configuration options related to the Perl module output -#--------------------------------------------------------------------------- -GENERATE_PERLMOD = NO -PERLMOD_LATEX = NO -PERLMOD_PRETTY = YES -PERLMOD_MAKEVAR_PREFIX = -#--------------------------------------------------------------------------- -# Configuration options related to the preprocessor -#--------------------------------------------------------------------------- -ENABLE_PREPROCESSING = YES -MACRO_EXPANSION = NO -EXPAND_ONLY_PREDEF = NO -SEARCH_INCLUDES = YES -INCLUDE_PATH = -INCLUDE_FILE_PATTERNS = -PREDEFINED = -EXPAND_AS_DEFINED = -SKIP_FUNCTION_MACROS = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to external references -#--------------------------------------------------------------------------- -TAGFILES = ../libgenerator/libgenerator.tag=../libgenerator -GENERATE_TAGFILE = cpythonbackend.tag -ALLEXTERNALS = NO -EXTERNAL_GROUPS = YES -PERL_PATH = /usr/bin/perl -#--------------------------------------------------------------------------- -# Configuration options related to the dot tool -#--------------------------------------------------------------------------- -CLASS_DIAGRAMS = YES -MSCGEN_PATH = -HIDE_UNDOC_RELATIONS = YES -HAVE_DOT = YES -DOT_FONTNAME = FreeSans -DOT_FONTSIZE = 10 -DOT_FONTPATH = -CLASS_GRAPH = YES -COLLABORATION_GRAPH = YES -GROUP_GRAPHS = NO -UML_LOOK = NO -TEMPLATE_RELATIONS = NO -INCLUDE_GRAPH = NO -INCLUDED_BY_GRAPH = NO -CALL_GRAPH = NO -CALLER_GRAPH = NO -GRAPHICAL_HIERARCHY = YES -DIRECTORY_GRAPH = NO -DOT_IMAGE_FORMAT = png -DOT_PATH = -DOTFILE_DIRS = -DOT_GRAPH_MAX_NODES = 50 -MAX_DOT_GRAPH_DEPTH = 1000 -DOT_TRANSPARENT = NO -DOT_MULTI_TARGETS = NO -GENERATE_LEGEND = YES -DOT_CLEANUP = YES -#--------------------------------------------------------------------------- -# Configuration::additions related to the search engine -#--------------------------------------------------------------------------- -SEARCHENGINE = NO From c131fb7e27f0116bb5fc212a11e05bf38a061942 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 15 Sep 2010 17:36:58 -0300 Subject: [PATCH 010/564] Add "doc" target to be able to build the docs out of the source directory. --- .gitignore | 1 - CMakeLists.txt | 1 + doc/Makefile | 88 ------------------------------------- doc/{conf.py => conf.py.in} | 6 +-- 4 files changed, 4 insertions(+), 92 deletions(-) delete mode 100644 doc/Makefile rename doc/{conf.py => conf.py.in} (96%) diff --git a/.gitignore b/.gitignore index fa13dcc5..40d69886 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,3 @@ build .preprocessed.tmp .*.swp *.kdev4 -doc/_build diff --git a/CMakeLists.txt b/CMakeLists.txt index ab604af9..8bb2d464 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -121,6 +121,7 @@ if (BUILD_TESTS) endif() add_subdirectory(libshiboken) +add_subdirectory(doc) if (BUILD_TESTS) add_subdirectory(tests) diff --git a/doc/Makefile b/doc/Makefile deleted file mode 100644 index 69b857c5..00000000 --- a/doc/Makefile +++ /dev/null @@ -1,88 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf _build/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html - @echo - @echo "Build finished. The HTML pages are in _build/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) _build/dirhtml - @echo - @echo "Build finished. The HTML pages are in _build/dirhtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in _build/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) _build/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in _build/qthelp, like this:" - @echo "# qcollectiongenerator _build/qthelp/PyQtB.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile _build/qthelp/PyQtB.qhc" - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex - @echo - @echo "Build finished; the LaTeX files are in _build/latex." - @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ - "run these through (pdf)latex." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes - @echo - @echo "The overview file is in _build/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in _build/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) _build/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in _build/doctest/output.txt." diff --git a/doc/conf.py b/doc/conf.py.in similarity index 96% rename from doc/conf.py rename to doc/conf.py.in index 21091828..e81c9c67 100644 --- a/doc/conf.py +++ b/doc/conf.py.in @@ -29,7 +29,7 @@ """ # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_templates'] # The suffix of source filenames. source_suffix = '.rst' @@ -104,7 +104,7 @@ #} # Add any paths that contain custom themes here, relative to this directory. -html_theme_path = ['_themes'] +html_theme_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_themes'] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". @@ -125,7 +125,7 @@ # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. From 091d0efcffa7bb80b653a343d6d41fd8c2fa0b23 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 15 Sep 2010 18:24:59 -0300 Subject: [PATCH 011/564] Remove reference to specific versions of other projects. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Renato Araújo Luciano Wolf --- doc/compiling.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/compiling.rst b/doc/compiling.rst index 7958d573..2b4f8c8b 100644 --- a/doc/compiling.rst +++ b/doc/compiling.rst @@ -10,9 +10,9 @@ Build requirements ^^^^^^^^^^^^^^^^^^ + CMake >= 2.6.0 -+ Python 2.5 (2.6 recommended) ++ Python >= 2.5, but < 3.0 + Qt4 libraries and development headers >= 4.5 (4.6 recommended) -+ api-extractor + generator runner >= 0.4 ++ api-extractor + generator runner Building and installing ^^^^^^^^^^^^^^^^^^^^^^^ From 4914a426267dd6f6cf852445f071650b5c0f7971 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 16 Sep 2010 16:05:04 -0300 Subject: [PATCH 012/564] Add missing CMakeLists.txt file. --- doc/CMakeLists.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 doc/CMakeLists.txt diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 00000000..d78844dc --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,10 @@ + +find_program(SPHINX sphinx-build DOC "Path to sphinx-build binary.") + +if (SPHINX) + message("-- sphinx-build - found") + configure_file(conf.py.in conf.py @ONLY) + add_custom_target(doc ${SPHINX} -b html -c . ${CMAKE_CURRENT_SOURCE_DIR} html ) +else() + message("-- sphinx-build - not found! doc target disabled") +endif() \ No newline at end of file From 42a3b42f8a00e94dd10e786210739fee7878cf51 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 16 Sep 2010 19:12:33 -0300 Subject: [PATCH 013/564] Fix bug#339 - "RuntimeError when accessing mousepress event object" Reviewer: Luciano Wolf Lauro Moura --- cppgenerator.cpp | 35 ++++++++++++++----- tests/libsample/objecttype.cpp | 6 ++++ tests/libsample/objecttype.h | 4 ++- .../ownership_invalidate_after_use_test.py | 21 +++++++++++ tests/samplebinding/typesystem_sample.xml | 3 ++ 5 files changed, 59 insertions(+), 10 deletions(-) diff --git a/cppgenerator.cpp b/cppgenerator.cpp index 89efd3b3..3e95f0ab 100644 --- a/cppgenerator.cpp +++ b/cppgenerator.cpp @@ -546,6 +546,16 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu s << argConversions.join(",\n") << endl; s << INDENT << "));" << endl; } + + bool invalidateReturn = false; + foreach (FunctionModification funcMod, func->modifications()) { + foreach (ArgumentModification argMod, funcMod.argument_mods) { + if (argMod.resetAfterUse) + s << INDENT << "bool invalidadeArg" << argMod.index << " = PyTuple_GET_ITEM(pyargs, " << argMod.index - 1 << ")->ob_refcnt == 1;" << endl; + else if (argMod.index == 0 && argMod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::CppOwnership) + invalidateReturn = true; + } + } s << endl; CodeSnipList snips; @@ -564,6 +574,9 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu s << INDENT; s << "Shiboken::AutoDecRef " PYTHON_RETURN_VAR "(PyObject_Call(py_override, pyargs, NULL));" << endl; if (type) { + if (invalidateReturn) + s << INDENT << "bool invalidadeArg0 = " PYTHON_RETURN_VAR "->ob_refcnt == 1;" << endl; + s << INDENT << "// An error happened in python code!" << endl; s << INDENT << "if (" PYTHON_RETURN_VAR ".isNull()) {" << endl; { @@ -651,15 +664,19 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu } } - bool transferReturnToCpp = false; - foreach (FunctionModification func_mod, func->modifications()) { - foreach (ArgumentModification arg_mod, func_mod.argument_mods) { - if (arg_mod.resetAfterUse) { + if (invalidateReturn) { + s << INDENT << "if (invalidadeArg0)" << endl; + Indentation indentation(INDENT); + s << INDENT << "BindingManager::instance().invalidateWrapper(" << PYTHON_RETURN_VAR ".object());" << endl; + } + + foreach (FunctionModification funcMod, func->modifications()) { + foreach (ArgumentModification argMod, funcMod.argument_mods) { + if (argMod.resetAfterUse) { + s << INDENT << "if (invalidadeArg" << argMod.index << ")" << endl; + Indentation indentation(INDENT); s << INDENT << "BindingManager::instance().invalidateWrapper(PyTuple_GET_ITEM(pyargs, "; - s << (arg_mod.index - 1) << "));" << endl; - } else if ((arg_mod.index == 0) && (arg_mod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::CppOwnership)) { - s << INDENT << "BindingManager::instance().invalidateWrapper(" << PYTHON_RETURN_VAR ".object());" << endl; - transferReturnToCpp = true; + s << (argMod.index - 1) << "));" << endl; } } } @@ -671,7 +688,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu } if (type) { - if (!transferReturnToCpp && (func->type()->isObject() || func->type()->isValuePointer()) ) { + if (!invalidateReturn && (func->type()->isObject() || func->type()->isValuePointer()) ) { s << INDENT << "if (" << PYTHON_RETURN_VAR << "->ob_refcnt < 2) {" << endl; { Indentation indent(INDENT); diff --git a/tests/libsample/objecttype.cpp b/tests/libsample/objecttype.cpp index ea3c78e7..c1407d23 100644 --- a/tests/libsample/objecttype.cpp +++ b/tests/libsample/objecttype.cpp @@ -166,6 +166,12 @@ ObjectType::processEvent(ObjectTypeList objects, Event *event) } +void +ObjectType::callInvalidateEvent(Event* event) +{ + invalidateEvent(event); +} + void ObjectType::setLayout(ObjectTypeLayout* l) { diff --git a/tests/libsample/objecttype.h b/tests/libsample/objecttype.h index c3bd8c62..b09b402e 100644 --- a/tests/libsample/objecttype.h +++ b/tests/libsample/objecttype.h @@ -78,6 +78,9 @@ class LIBSAMPLE_API ObjectType virtual bool event(Event* event); static int processEvent(ObjectTypeList objects, Event *event); + void callInvalidateEvent(Event* event); + virtual void invalidateEvent(Event* event) {} + // This nonsense method emulate QWidget.setLayout method // All layout objects will became children of this object. void setLayout(ObjectTypeLayout* layout); @@ -99,7 +102,6 @@ class LIBSAMPLE_API ObjectType void setObject(const Null&); int callId() const; - private: ObjectType(const ObjectType&); ObjectType& operator=(const ObjectType&); diff --git a/tests/samplebinding/ownership_invalidate_after_use_test.py b/tests/samplebinding/ownership_invalidate_after_use_test.py index 80f252d5..5a03fc47 100644 --- a/tests/samplebinding/ownership_invalidate_after_use_test.py +++ b/tests/samplebinding/ownership_invalidate_after_use_test.py @@ -42,6 +42,22 @@ def event(self, event): self.type_of_last_event = event.eventType() return True +class MyObjectType (ObjectType): + def __init__(self): + super(MyObjectType, self).__init__() + self.fail = False + + def event(self, ev): + self.callInvalidateEvent(ev) + try: + ev.eventType() + except: + self.fail = True + raise + return True + + def invalidateEvent(self, ev): + pass class OwnershipInvalidateAfterUseTest(unittest.TestCase): '''Ownership tests for cases of invalidation of Python wrapper after use.''' @@ -61,6 +77,11 @@ def testObjectInvalidatedAfterUseAsParameter(self): self.assertEqual(eot.type_of_last_event, Event.ANY_EVENT) self.assertRaises(RuntimeError, ot.event, eot.last_event) + def testit(self): + obj = MyObjectType() + obj.causeEvent(Event.BASIC_EVENT) + self.assertFalse(obj.fail) + if __name__ == '__main__': unittest.main() diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index de262c9e..40b70ab4 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -141,6 +141,9 @@ + + + From 2b8f4f3d19256f306be1c354eb62a7b367926d43 Mon Sep 17 00:00:00 2001 From: Lauro Neto Date: Fri, 17 Sep 2010 20:13:58 -0300 Subject: [PATCH 014/564] Fix OverloadData::isSingleArgument MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now returning true *only* when exactly all overloads accept exactly 1 argument. Fixes compilation of QAudioInput and QAudioOutput from QtMultimedia. Both have start() and start(QIODevice*) overloads, and the previous code was generating 'arg' instead of 'pyargs'. Reviewer: Renato Araújo Luciano Wolf --- overloaddata.cpp | 2 +- tests/libsample/overload.h | 3 +++ tests/samplebinding/typesystem_sample.xml | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/overloaddata.cpp b/overloaddata.cpp index 1d81cab1..a71091ea 100644 --- a/overloaddata.cpp +++ b/overloaddata.cpp @@ -572,7 +572,7 @@ bool OverloadData::isSingleArgument(const AbstractMetaFunctionList& overloads) { bool singleArgument = true; foreach (const AbstractMetaFunction* func, overloads) { - if (func->arguments().size() - numberOfRemovedArguments(func) > 1) { + if (func->arguments().size() - numberOfRemovedArguments(func) != 1) { singleArgument = false; break; } diff --git a/tests/libsample/overload.h b/tests/libsample/overload.h index 739c4065..36b30f2b 100644 --- a/tests/libsample/overload.h +++ b/tests/libsample/overload.h @@ -57,6 +57,9 @@ class LIBSAMPLE_API Overload inline int intOverloads(const Point& p, double d) { return 1; } inline int intOverloads(int i, int i2) { return 2; } inline int intOverloads(int i, int removedArg, double d) { return 3; } + + void singleOverload(Point* x) {} + Point* singleOverload() {return new Point();} }; #endif // OVERLOAD_H diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 40b70ab4..4f98dff4 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -978,6 +978,11 @@ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%CPPSELF.%FUNCTION_NAME(%1, 2, %3)); + + + + + From 4493cee8e2fe680e89f2a730d50646c95c45358f Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Mon, 20 Sep 2010 11:14:26 -0300 Subject: [PATCH 015/564] Added tests for anonymous global and class bound enums. --- tests/libsample/samplenamespace.h | 14 ++++++++++++++ tests/samplebinding/enum_test.py | 11 +++++++++++ tests/samplebinding/typesystem_sample.xml | 3 +++ 3 files changed, 28 insertions(+) diff --git a/tests/libsample/samplenamespace.h b/tests/libsample/samplenamespace.h index 2533b974..d00bbb1f 100644 --- a/tests/libsample/samplenamespace.h +++ b/tests/libsample/samplenamespace.h @@ -29,6 +29,12 @@ class ObjectType; +// Anonymous global enum +enum { + AnonymousGlobalEnum_Value0, + AnonymousGlobalEnum_Value1 +}; + namespace SampleNamespace { @@ -50,6 +56,14 @@ enum OutValue { TwoOut }; +// Anonymous non-global enum. +// This counts as a class enum, since C++ namespaces +// are represented as classes in Python. +enum { + AnonymousClassEnum_Value0, + AnonymousClassEnum_Value1 +}; + LIBSAMPLE_API OutValue enumInEnumOut(InValue in); LIBSAMPLE_API int getNumber(Option opt); diff --git a/tests/samplebinding/enum_test.py b/tests/samplebinding/enum_test.py index 65ec1af3..71ebef60 100644 --- a/tests/samplebinding/enum_test.py +++ b/tests/samplebinding/enum_test.py @@ -28,6 +28,7 @@ import unittest +import sample from sample import SampleNamespace, ObjectType, Event class EnumTest(unittest.TestCase): @@ -72,6 +73,16 @@ def testEnumItemAsDefaultValueToIntArgument(self): self.assertEqual(SampleNamespace.enumItemAsDefaultValueToIntArgument(SampleNamespace.ZeroOut), SampleNamespace.ZeroOut) self.assertEqual(SampleNamespace.enumItemAsDefaultValueToIntArgument(123), 123) + def testAnonymousGlobalEnums(self): + '''Checks availability of anonymous global enum items.''' + self.assertEqual(sample.AnonymousGlobalEnum_Value0, 0) + self.assertEqual(sample.AnonymousGlobalEnum_Value1, 1) + + def testAnonymousClassEnums(self): + '''Checks availability of anonymous class enum items.''' + self.assertEqual(SampleNamespace.AnonymousClassEnum_Value0, 0) + self.assertEqual(SampleNamespace.AnonymousClassEnum_Value1, 1) + class EnumOverloadTest(unittest.TestCase): '''Test case for overloads involving enums''' diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 4f98dff4..88cf7689 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -87,6 +87,9 @@ + + + From 9d5a8614ae4a71c5da1d4f9e56dfed1c9dfe58df Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Mon, 20 Sep 2010 11:22:24 -0300 Subject: [PATCH 016/564] Anonymous enums now supported. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Due to their nature anonymous enums aren't considered type by the binding generator, rather the enum's values are used wrapped like C++ integer constants. Global enum values are added to the Python module with "PyModule_AddIntConstant(...)", class related anonymous enum values are merely added to the wrapper class dictionary as Python integers. Reviewed by Luciano Wolf Reviewed by Renato Araújo --- cppgenerator.cpp | 118 ++++++++++++++++++++++++++++---------------- headergenerator.cpp | 4 ++ 2 files changed, 79 insertions(+), 43 deletions(-) diff --git a/cppgenerator.cpp b/cppgenerator.cpp index 3e95f0ab..2df2bae9 100644 --- a/cppgenerator.cpp +++ b/cppgenerator.cpp @@ -372,6 +372,9 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl foreach (AbstractMetaEnum* cppEnum, metaClass->enums()) { + if (cppEnum->isAnonymous()) + continue; + bool hasFlags = cppEnum->typeEntry()->flags(); if (hasFlags) { writeFlagsMethods(s, cppEnum); @@ -2834,34 +2837,44 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu QString addFunction; if (cppEnum->enclosingClass()) addFunction = "PyDict_SetItemString(" + cpythonTypeName(cppEnum->enclosingClass()) + ".super.ht_type.tp_dict,"; + else if (cppEnum->isAnonymous()) + addFunction = "PyModule_AddIntConstant(module,"; else addFunction = "PyModule_AddObject(module,"; - s << INDENT << "// init enum class: " << cppEnum->name() << endl; - s << INDENT << cpythonTypeNameExt(cppEnum->typeEntry()) << " = &" << cpythonTypeName(cppEnum->typeEntry()) << ';' << endl; - s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << cpythonName << "_Type) < 0)" << endl; - s << INDENT << INDENT << "return;" << endl; + s << INDENT << "// init "; + if (cppEnum->isAnonymous()) + s << "anonymous enum identified by enum value: "; + else + s << "enum: "; + s << cppEnum->name() << endl; + + if (!cppEnum->isAnonymous()) { + s << INDENT << cpythonTypeNameExt(cppEnum->typeEntry()) << " = &" << cpythonTypeName(cppEnum->typeEntry()) << ';' << endl; + s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << cpythonName << "_Type) < 0)" << endl; + s << INDENT << INDENT << "return;" << endl; - s << INDENT << "Py_INCREF(&" << cpythonName << "_Type);" << endl; + s << INDENT << "Py_INCREF(&" << cpythonName << "_Type);" << endl; - s << INDENT << addFunction << endl; - s << INDENT << INDENT << INDENT << '\"' << cppEnum->name() << "\","; - s << "((PyObject*)&" << cpythonName << "_Type));" << endl << endl; + s << INDENT << addFunction << endl; + s << INDENT << INDENT << INDENT << '\"' << cppEnum->name() << "\","; + s << "((PyObject*)&" << cpythonName << "_Type));" << endl << endl; - FlagsTypeEntry* flags = cppEnum->typeEntry()->flags(); - if (flags) { - QString flagsName = cpythonFlagsName(flags); - s << INDENT << "// init flags class: " << flags->name() << endl; - s << INDENT << cpythonTypeNameExt(flags) << " = &" << cpythonTypeName(flags) << ';' << endl; + FlagsTypeEntry* flags = cppEnum->typeEntry()->flags(); + if (flags) { + QString flagsName = cpythonFlagsName(flags); + s << INDENT << "// init flags class: " << flags->name() << endl; + s << INDENT << cpythonTypeNameExt(flags) << " = &" << cpythonTypeName(flags) << ';' << endl; - s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << flagsName << "_Type) < 0)" << endl; - s << INDENT << INDENT << "return;" << endl; + s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << flagsName << "_Type) < 0)" << endl; + s << INDENT << INDENT << "return;" << endl; - s << INDENT << "Py_INCREF(&" << flagsName << "_Type);" << endl; + s << INDENT << "Py_INCREF(&" << flagsName << "_Type);" << endl; - s << INDENT << addFunction << endl; - s << INDENT << INDENT << INDENT << '\"' << flags->flagsName() << "\","; - s << "((PyObject*)&" << flagsName << "_Type));" << endl << endl; + s << INDENT << addFunction << endl; + s << INDENT << INDENT << INDENT << '\"' << flags->flagsName() << "\","; + s << "((PyObject*)&" << flagsName << "_Type));" << endl << endl; + } } @@ -2869,44 +2882,61 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu if (cppEnum->typeEntry()->isEnumValueRejected(enumValue->name())) continue; - s << INDENT << "enum_item = Shiboken::SbkEnumObject_New(&"; - s << cpythonName << "_Type," << endl; - { - Indentation indent(INDENT); - s << INDENT; + QString enumValueText; #ifdef AVOID_PROTECTED_HACK - if (!cppEnum->isProtected()) { + if (!cppEnum->isProtected()) { #endif - s << "(long) "; - if (cppEnum->enclosingClass()) - s << cppEnum->enclosingClass()->qualifiedCppName() << "::"; - s << enumValue->name(); + enumValueText = "(long) "; + if (cppEnum->enclosingClass()) + enumValueText += cppEnum->enclosingClass()->qualifiedCppName() + "::"; + enumValueText += enumValue->name(); #ifdef AVOID_PROTECTED_HACK - } else { - s << enumValue->value(); - } + } else { + enumValueText += enumValue->value(); + } #endif - s << ", \"" << enumValue->name() << "\");" << endl; + + bool shouldDecrefNumber = false; + QString enumItemText = "enum_item"; + if (!cppEnum->isAnonymous()) { + s << INDENT << "enum_item = Shiboken::SbkEnumObject_New(&"; + s << cpythonName << "_Type," << endl; + { + Indentation indent(INDENT); + s << INDENT << enumValueText << ", \"" << enumValue->name() << "\");" << endl; + } + } else if (cppEnum->enclosingClass()) { + s << INDENT << "enum_item = PyInt_FromLong(" << enumValueText << ");" << endl; + shouldDecrefNumber = true; + } else { + enumItemText = enumValueText; } s << INDENT << addFunction << endl; { Indentation indent(INDENT); - s << INDENT << '"' << enumValue->name() << "\", enum_item);" << endl; + s << INDENT << '"' << enumValue->name() << "\", " << enumItemText << ");" << endl; } - s << INDENT << "PyDict_SetItemString(" << cpythonName << "_Type.tp_dict," << endl; - { - Indentation indent(INDENT); - s << INDENT << '"' << enumValue->name() << "\", enum_item);" << endl; + if (shouldDecrefNumber) + s << INDENT << "Py_DECREF(enum_item);" << endl; + + if (!cppEnum->isAnonymous()) { + s << INDENT << "PyDict_SetItemString(" << cpythonName << "_Type.tp_dict," << endl; + { + Indentation indent(INDENT); + s << INDENT << '"' << enumValue->name() << "\", enum_item);" << endl; + } } } - // TypeResolver stuff - s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver(\""; - if (cppEnum->enclosingClass()) - s << cppEnum->enclosingClass()->qualifiedCppName() << "::"; - s << cppEnum->name() << "\");\n"; + if (!cppEnum->isAnonymous()) { + // TypeResolver stuff + s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver(\""; + if (cppEnum->enclosingClass()) + s << cppEnum->enclosingClass()->qualifiedCppName() << "::"; + s << cppEnum->name() << "\");\n"; + } s << endl; @@ -3533,6 +3563,8 @@ void CppGenerator::finishGeneration() s << "// Enum definitions "; s << "------------------------------------------------------------" << endl; foreach (const AbstractMetaEnum* cppEnum, globalEnums()) { + if (cppEnum->isAnonymous()) + continue; writeEnumDefinition(s, cppEnum); s << endl; } diff --git a/headergenerator.cpp b/headergenerator.cpp index 90c27b81..2e060f42 100644 --- a/headergenerator.cpp +++ b/headergenerator.cpp @@ -321,6 +321,8 @@ void HeaderGenerator::finishGeneration() macrosStream << "// Macros for type check" << endl; foreach (const AbstractMetaEnum* cppEnum, globalEnums()) { + if (cppEnum->isAnonymous()) + continue; includes << cppEnum->typeEntry()->include(); writeTypeConverterDecl(convDecl, cppEnum->typeEntry()); convDecl << endl; @@ -336,6 +338,8 @@ void HeaderGenerator::finishGeneration() includes << classType->include(); foreach (const AbstractMetaEnum* cppEnum, metaClass->enums()) { + if (cppEnum->isAnonymous()) + continue; EnumTypeEntry* enumType = cppEnum->typeEntry(); includes << enumType->include(); writeTypeConverterDecl(convDecl, enumType); From a02e6fff64cdfcf2022c73d03d779a2584544842 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 17 Sep 2010 14:52:05 -0300 Subject: [PATCH 017/564] Do not show shiboken options twice on --help. --- headergenerator.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/headergenerator.h b/headergenerator.h index c1f56b00..9802a104 100644 --- a/headergenerator.h +++ b/headergenerator.h @@ -31,6 +31,8 @@ */ class HeaderGenerator : public ShibokenGenerator { +public: + QMap options() const { return QMap(); } protected: QString fileNameForClass(const AbstractMetaClass* metaClass) const; void generateClass(QTextStream& s, const AbstractMetaClass* metaClass); From 231253beff97ce9d81d63ee437b833cc73ed1142 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Mon, 20 Sep 2010 17:26:09 -0300 Subject: [PATCH 018/564] Shiboken generator code moved to the directory generator. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Renato Araújo Luciano Wolf --- CMakeLists.txt | 95 +++++-------------- .../cppgenerator.cpp | 0 cppgenerator.h => generator/cppgenerator.h | 0 .../headergenerator.cpp | 0 .../headergenerator.h | 0 main.cpp => generator/main.cpp | 0 .../overloaddata.cpp | 0 overloaddata.h => generator/overloaddata.h | 0 shiboken.cpp => generator/shiboken.cpp | 0 .../shibokengenerator.cpp | 0 .../shibokengenerator.h | 0 libshiboken/CMakeLists.txt | 8 ++ tests/CMakeLists.txt | 23 +++++ tests/otherbinding/CMakeLists.txt | 2 +- tests/samplebinding/CMakeLists.txt | 2 +- 15 files changed, 55 insertions(+), 75 deletions(-) rename cppgenerator.cpp => generator/cppgenerator.cpp (100%) rename cppgenerator.h => generator/cppgenerator.h (100%) rename headergenerator.cpp => generator/headergenerator.cpp (100%) rename headergenerator.h => generator/headergenerator.h (100%) rename main.cpp => generator/main.cpp (100%) rename overloaddata.cpp => generator/overloaddata.cpp (100%) rename overloaddata.h => generator/overloaddata.h (100%) rename shiboken.cpp => generator/shiboken.cpp (100%) rename shibokengenerator.cpp => generator/shibokengenerator.cpp (100%) rename shibokengenerator.h => generator/shibokengenerator.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8bb2d464..2830bcba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,17 +6,21 @@ cmake_minimum_required(VERSION 2.6) set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules/ ${CMAKE_MODULE_PATH}) -find_package(Qt4 4.5.0 REQUIRED) -find_package(ApiExtractor 0.8 REQUIRED) -find_package(GeneratorRunner 0.6.1 REQUIRED) -find_package(PythonLibs REQUIRED) -find_package(PythonInterpWithDebug REQUIRED) +find_package(Qt4 4.5.0) +find_package(ApiExtractor 0.8) +find_package(GeneratorRunner 0.6.1) +find_package(PythonLibs) +find_package(PythonInterpWithDebug) add_definitions(${QT_DEFINITIONS}) +set(shiboken_MAJOR_VERSION "0") +set(shiboken_MINOR_VERSION "5") +set(shiboken_MICRO_VERSION "1") +set(shiboken_VERSION "${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VERSION}.${shiboken_MICRO_VERSION}") + option(AVOID_PROTECTED_HACK "Avoid protected hack on generated bindings." FALSE) option(BUILD_TESTS "Build tests." TRUE) -option(ENABLE_VERSION_SUFFIX "Used to use current version in suffix to generated files. This is used to allow multiples versions installed simultaneous." FALSE) if(MSVC) set(CMAKE_CXX_FLAGS "/Zc:wchar_t- /GR /EHsc /DWIN32 /D_WINDOWS /D_SCL_SECURE_NO_WARNINGS") @@ -35,6 +39,9 @@ else() endif() endif() +set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) +set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE) + if (WIN32) set(PATH_SEP "\;") else() @@ -48,45 +55,6 @@ else() message(STATUS "Using protected hack!") endif() -set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) -set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE) - -set(shiboken_MAJOR_VERSION "0") -set(shiboken_MINOR_VERSION "5") -set(shiboken_MICRO_VERSION "1") -set(shiboken_VERSION "${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VERSION}.${shiboken_MICRO_VERSION}") -if(ENABLE_VERSION_SUFFIX) - set(shiboken_SUFFIX "-${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VERSION}") -else() - set(shiboken_SUFFIX "") -endif() - -set(shiboken_SRC -cppgenerator.cpp -headergenerator.cpp -overloaddata.cpp -shiboken.cpp -shibokengenerator.cpp -) - -include_directories(${CMAKE_CURRENT_SOURCE_DIR} - ${APIEXTRACTOR_INCLUDE_DIR} - ${GENERATORRUNNER_INCLUDE_DIR} - ${QT_INCLUDE_DIR} - ${QT_QTCORE_INCLUDE_DIR}) - -add_library(shiboken_generator SHARED ${shiboken_SRC}) -set_property(TARGET shiboken_generator PROPERTY PREFIX "") - -target_link_libraries(shiboken_generator - ${APIEXTRACTOR_LIBRARY} - ${GENERATORRUNNER_LIBRARY} - ${QT_QTCORE_LIBRARY}) - -add_executable(shiboken main.cpp) -set_target_properties(shiboken PROPERTIES OUTPUT_NAME shiboken${shiboken_SUFFIX}) -target_link_libraries(shiboken ${QT_QTCORE_LIBRARY}) - # uninstall target configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" @@ -94,28 +62,6 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake" add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") -# Detect if the python libs were compiled in debug mode -execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "from distutils import sysconfig; \\ - print sysconfig.get_config_var('Py_DEBUG')" - OUTPUT_VARIABLE PY_DEBUG - OUTPUT_STRIP_TRAILING_WHITESPACE) - -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - if(NOT PYTHON_DEBUG_LIBRARIES) - message(FATAL_ERROR "Python debug library not found. Try compile shiboken with -DCMAKE_BUILD_TYPE=Release") - endif() - if(NOT PY_DEBUG) - message(WARNING "Compiling shiboken with debug enabled, but the python executable was not compiled with debug support.") - else() - add_definitions("-DPy_DEBUG") - endif() - set(SBK_PYTHON_LIBRARIES ${PYTHON_DEBUG_LIBRARIES}) -else() - set(SBK_PYTHON_LIBRARIES ${PYTHON_LIBRARIES}) - add_definitions("-DNDEBUG") -endif() - if (BUILD_TESTS) enable_testing() endif() @@ -123,8 +69,15 @@ endif() add_subdirectory(libshiboken) add_subdirectory(doc) -if (BUILD_TESTS) - add_subdirectory(tests) +# deps found, compile the generator. +if (QT4_FOUND AND ApiExtractor_FOUND AND GeneratorRunner_FOUND AND PYTHONLIBS_FOUND AND PYTHONINTERP_FOUND) + add_subdirectory(generator) + + if (BUILD_TESTS) + add_subdirectory(tests) + endif() +else() + message("!! Some dependencies were not found, shiboken generator compilation disabled!") endif() add_subdirectory(data) @@ -138,8 +91,4 @@ add_custom_target(dist echo "Source package created at ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar.bz2.\n" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) -add_dependencies(shiboken shiboken_generator) - -install(TARGETS shiboken_generator DESTINATION "${GENERATORRUNNER_PLUGIN_DIR}") -install(TARGETS shiboken DESTINATION bin) diff --git a/cppgenerator.cpp b/generator/cppgenerator.cpp similarity index 100% rename from cppgenerator.cpp rename to generator/cppgenerator.cpp diff --git a/cppgenerator.h b/generator/cppgenerator.h similarity index 100% rename from cppgenerator.h rename to generator/cppgenerator.h diff --git a/headergenerator.cpp b/generator/headergenerator.cpp similarity index 100% rename from headergenerator.cpp rename to generator/headergenerator.cpp diff --git a/headergenerator.h b/generator/headergenerator.h similarity index 100% rename from headergenerator.h rename to generator/headergenerator.h diff --git a/main.cpp b/generator/main.cpp similarity index 100% rename from main.cpp rename to generator/main.cpp diff --git a/overloaddata.cpp b/generator/overloaddata.cpp similarity index 100% rename from overloaddata.cpp rename to generator/overloaddata.cpp diff --git a/overloaddata.h b/generator/overloaddata.h similarity index 100% rename from overloaddata.h rename to generator/overloaddata.h diff --git a/shiboken.cpp b/generator/shiboken.cpp similarity index 100% rename from shiboken.cpp rename to generator/shiboken.cpp diff --git a/shibokengenerator.cpp b/generator/shibokengenerator.cpp similarity index 100% rename from shibokengenerator.cpp rename to generator/shibokengenerator.cpp diff --git a/shibokengenerator.h b/generator/shibokengenerator.h similarity index 100% rename from shibokengenerator.h rename to generator/shibokengenerator.h diff --git a/libshiboken/CMakeLists.txt b/libshiboken/CMakeLists.txt index bfd160b1..f21681f5 100644 --- a/libshiboken/CMakeLists.txt +++ b/libshiboken/CMakeLists.txt @@ -1,4 +1,12 @@ project(libshiboken) + +option(ENABLE_VERSION_SUFFIX "Used to use current version in suffix to generated files. This is used to allow multiples versions installed simultaneous." FALSE) +if(ENABLE_VERSION_SUFFIX) + set(shiboken_SUFFIX "-${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VERSION}") +else() + set(shiboken_SUFFIX "") +endif() + #Find installed sparsehash find_path(SPARSEHASH_INCLUDE_PATH sparseconfig.h PATH_SUFFIXES "/google/sparsehash") if(SPARSEHASH_INCLUDE_PATH) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index dc5e52d4..48d9de48 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,5 +1,28 @@ add_subdirectory(libsample) add_subdirectory(libother) + +# Detect if the python libs were compiled in debug mode +execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c "from distutils import sysconfig; \\ + print sysconfig.get_config_var('Py_DEBUG')" + OUTPUT_VARIABLE PY_DEBUG + OUTPUT_STRIP_TRAILING_WHITESPACE) + +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + if(NOT PYTHON_DEBUG_LIBRARIES) + message(FATAL_ERROR "Python debug library not found. Try compile shiboken with -DCMAKE_BUILD_TYPE=Release") + endif() + if(NOT PY_DEBUG) + message(WARNING "Compiling shiboken with debug enabled, but the python executable was not compiled with debug support.") + else() + add_definitions("-DPy_DEBUG") + endif() + set(SBK_PYTHON_LIBRARIES ${PYTHON_DEBUG_LIBRARIES}) +else() + set(SBK_PYTHON_LIBRARIES ${PYTHON_LIBRARIES}) + add_definitions("-DNDEBUG") +endif() + add_subdirectory(samplebinding) add_subdirectory(otherbinding) diff --git a/tests/otherbinding/CMakeLists.txt b/tests/otherbinding/CMakeLists.txt index 25294bf7..3a16dd67 100644 --- a/tests/otherbinding/CMakeLists.txt +++ b/tests/otherbinding/CMakeLists.txt @@ -14,7 +14,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/other/other_module_wrapper.cpp ) add_custom_command(OUTPUT ${other_SRC} -COMMAND ${GENERATORRUNNER_BINARY} --generatorSet=${shiboken_BINARY_DIR}/shiboken_generator${CMAKE_RELEASE_POSTFIX}${CMAKE_DEBUG_POSTFIX} --enable-parent-ctor-heuristic +COMMAND ${GENERATORRUNNER_BINARY} --generatorSet=${generators_BINARY_DIR}/shiboken_generator${CMAKE_RELEASE_POSTFIX}${CMAKE_DEBUG_POSTFIX} --enable-parent-ctor-heuristic ${CMAKE_CURRENT_SOURCE_DIR}/global.h --include-paths=${libother_SOURCE_DIR}${PATH_SEP}${libsample_SOURCE_DIR}${PATH_SEP}${libsample_SOURCE_DIR}/.. --typesystem-paths=${CMAKE_CURRENT_SOURCE_DIR}${PATH_SEP}${sample_SOURCE_DIR} diff --git a/tests/samplebinding/CMakeLists.txt b/tests/samplebinding/CMakeLists.txt index 3536ce39..2de6deea 100644 --- a/tests/samplebinding/CMakeLists.txt +++ b/tests/samplebinding/CMakeLists.txt @@ -77,7 +77,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/valueandvirtual_wrapper.cpp ) add_custom_command(OUTPUT ${sample_SRC} -COMMAND ${GENERATORRUNNER_BINARY} --generatorSet=${shiboken_BINARY_DIR}/shiboken_generator${CMAKE_RELEASE_POSTFIX}${CMAKE_DEBUG_POSTFIX} --enable-parent-ctor-heuristic +COMMAND ${GENERATORRUNNER_BINARY} --generatorSet=${generators_BINARY_DIR}/shiboken_generator${CMAKE_RELEASE_POSTFIX}${CMAKE_DEBUG_POSTFIX} --enable-parent-ctor-heuristic ${CMAKE_CURRENT_SOURCE_DIR}/global.h --include-paths=${libsample_SOURCE_DIR} --typesystem-paths=${CMAKE_CURRENT_SOURCE_DIR} From e87fbe13223a7c53404846565e1c74d914e0eab2 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Mon, 20 Sep 2010 18:58:14 -0300 Subject: [PATCH 019/564] Use CMAKE__POSTFIX on config files, used for cmake and pkgconfig. Fixes bug #286. Reviewer: Hugo Parente Lima Luciano Wolf --- data/CMakeLists.txt | 6 ++++++ data/ShibokenConfig.cmake.in | 6 +++--- data/shiboken.pc.in | 2 +- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt index 85c9d6a9..9ad9381d 100644 --- a/data/CMakeLists.txt +++ b/data/CMakeLists.txt @@ -1,3 +1,9 @@ +if (CMAKE_BUILD_TYPE STREQUAL "Debug") + set(LIBRARY_OUTPUT_SUFFIX ${CMAKE_DEBUG_POSTFIX}) +else() + set(LIBRARY_OUTPUT_SUFFIX ${CMAKE_RELEASE_POSTFIX}) +endif() + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/ShibokenConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/ShibokenConfig.cmake" @ONLY) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/ShibokenConfigVersion.cmake.in" diff --git a/data/ShibokenConfig.cmake.in b/data/ShibokenConfig.cmake.in index 148c35b9..8d46e76a 100644 --- a/data/ShibokenConfig.cmake.in +++ b/data/ShibokenConfig.cmake.in @@ -3,9 +3,9 @@ SET(SHIBOKEN_INCLUDE_DIR "@CMAKE_INSTALL_PREFIX@/include/shiboken@shiboken_SUFFIX@") if(MSVC) - SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@.lib") + SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@.lib") elseif(WIN32) - SET(SHIBOKEN_LIBRARY "@CMAKE_INSTALL_PREFIX@/bin/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") + SET(SHIBOKEN_LIBRARY "@CMAKE_INSTALL_PREFIX@/bin/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") else() - SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") + SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") endif() diff --git a/data/shiboken.pc.in b/data/shiboken.pc.in index c54e84a4..0b3bdfd4 100644 --- a/data/shiboken.pc.in +++ b/data/shiboken.pc.in @@ -7,6 +7,6 @@ generator_location=@CMAKE_INSTALL_PREFIX@/bin/shiboken Name: shiboken Description: Support library for Python bindings created with Shiboken generator. Version: @shiboken_VERSION@ -Libs: -L${libdir} -lpython -lshiboken@shiboken_SUFFIX@ +Libs: -L${libdir} -lpython -lshiboken@shiboken_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@ Cflags: -I${includedir}/shiboken@shiboken_SUFFIX@ From 55a8b424067fcf3c6a2cc3f6f9b9708b17553a6f Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 21 Sep 2010 11:15:36 -0300 Subject: [PATCH 020/564] Add missing CMakeLists.txt file --- generator/CMakeLists.txt | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 generator/CMakeLists.txt diff --git a/generator/CMakeLists.txt b/generator/CMakeLists.txt new file mode 100644 index 00000000..89b2ef75 --- /dev/null +++ b/generator/CMakeLists.txt @@ -0,0 +1,32 @@ +project(generators) + +set(shiboken_SRC +cppgenerator.cpp +headergenerator.cpp +overloaddata.cpp +shiboken.cpp +shibokengenerator.cpp +) + +include_directories(${CMAKE_CURRENT_SOURCE_DIR} + ${APIEXTRACTOR_INCLUDE_DIR} + ${GENERATORRUNNER_INCLUDE_DIR} + ${QT_INCLUDE_DIR} + ${QT_QTCORE_INCLUDE_DIR}) + +add_library(shiboken_generator SHARED ${shiboken_SRC}) +set_property(TARGET shiboken_generator PROPERTY PREFIX "") + +target_link_libraries(shiboken_generator + ${APIEXTRACTOR_LIBRARY} + ${GENERATORRUNNER_LIBRARY} + ${QT_QTCORE_LIBRARY}) + +add_executable(shiboken main.cpp) +set_target_properties(shiboken PROPERTIES OUTPUT_NAME shiboken${shiboken_SUFFIX}) +target_link_libraries(shiboken ${QT_QTCORE_LIBRARY}) + +add_dependencies(shiboken shiboken_generator) + +install(TARGETS shiboken_generator DESTINATION "${GENERATORRUNNER_PLUGIN_DIR}") +install(TARGETS shiboken DESTINATION bin) From 06f1f83e0e8f39cde919bdb8a3441823bc5a5bb2 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Tue, 21 Sep 2010 13:41:55 -0300 Subject: [PATCH 021/564] Fixed function use to create wrapper based on QObject. Fixes bug #360. Reviewer: Hugo Parente Lima Luciano Wolf --- generator/headergenerator.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/generator/headergenerator.cpp b/generator/headergenerator.cpp index 2e060f42..095febb7 100644 --- a/generator/headergenerator.cpp +++ b/generator/headergenerator.cpp @@ -428,8 +428,12 @@ void HeaderGenerator::finishGeneration() s << "inline PyObject* createWrapper<" << metaClass->qualifiedCppName() << " >(const "; s << metaClass->qualifiedCppName() << "* cppobj, bool hasOwnership, bool isExactType)" << endl; s << '{' << endl; + s << INDENT << "const char* typeName = 0;" << endl; + s << INDENT << metaClass->qualifiedCppName() << "* value = const_cast<" << metaClass->qualifiedCppName() << "* >(cppobj);" << endl; + s << INDENT << "if (!isExactType)" << endl; + s << INDENT << INDENT << "typeName = typeid(*value).name();" << endl; s << INDENT << "PyObject* pyObj = Shiboken::SbkBaseWrapper_New(reinterpret_cast(SbkType<" << metaClass->qualifiedCppName() << " >())," - << "const_cast<" << metaClass->qualifiedCppName() << "*>(cppobj), hasOwnership, isExactType);" << endl; + << "value, hasOwnership, isExactType, typeName);" << endl; s << INDENT << "PySide::signalUpdateSource(pyObj);" << endl; s << INDENT << "return pyObj;" << endl; s << '}' << endl; From abdb20e1a2f1032b2e467ab13b004ff5c9fbd1a0 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Tue, 21 Sep 2010 13:45:46 -0300 Subject: [PATCH 022/564] Move Python debug check to root Cmake file. Reviewer: Hugo Parente Lima Luciano Wolf --- CMakeLists.txt | 23 +++++++++++++++++++++++ tests/CMakeLists.txt | 21 --------------------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2830bcba..8c831763 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,6 +62,29 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake" add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") +# Detect if the python libs were compiled in debug mode +execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c "from distutils import sysconfig; \\ + print sysconfig.get_config_var('Py_DEBUG')" + OUTPUT_VARIABLE PY_DEBUG + OUTPUT_STRIP_TRAILING_WHITESPACE) + +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + if(NOT PYTHON_DEBUG_LIBRARIES) + message(FATAL_ERROR "Python debug library not found. Try compile shiboken with -DCMAKE_BUILD_TYPE=Release") + endif() + if(NOT PY_DEBUG) + message(WARNING "Compiling shiboken with debug enabled, but the python executable was not compiled with debug support.") + else() + add_definitions("-DPy_DEBUG") + endif() + set(SBK_PYTHON_LIBRARIES ${PYTHON_DEBUG_LIBRARIES}) +else() + set(SBK_PYTHON_LIBRARIES ${PYTHON_LIBRARIES}) + add_definitions("-DNDEBUG") +endif() + + if (BUILD_TESTS) enable_testing() endif() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 48d9de48..e33305df 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,27 +1,6 @@ add_subdirectory(libsample) add_subdirectory(libother) -# Detect if the python libs were compiled in debug mode -execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "from distutils import sysconfig; \\ - print sysconfig.get_config_var('Py_DEBUG')" - OUTPUT_VARIABLE PY_DEBUG - OUTPUT_STRIP_TRAILING_WHITESPACE) - -if(CMAKE_BUILD_TYPE STREQUAL "Debug") - if(NOT PYTHON_DEBUG_LIBRARIES) - message(FATAL_ERROR "Python debug library not found. Try compile shiboken with -DCMAKE_BUILD_TYPE=Release") - endif() - if(NOT PY_DEBUG) - message(WARNING "Compiling shiboken with debug enabled, but the python executable was not compiled with debug support.") - else() - add_definitions("-DPy_DEBUG") - endif() - set(SBK_PYTHON_LIBRARIES ${PYTHON_DEBUG_LIBRARIES}) -else() - set(SBK_PYTHON_LIBRARIES ${PYTHON_LIBRARIES}) - add_definitions("-DNDEBUG") -endif() add_subdirectory(samplebinding) add_subdirectory(otherbinding) From c8cc5c1c819f23a3f98fbcc05cff3a15714f31d0 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Tue, 21 Sep 2010 15:44:39 -0300 Subject: [PATCH 023/564] The CMake configuration for PySide and Shiboken use the PYTHON_LIBRARIES variable to link against Python. This is not the correct way to link against Python on OS X. Instead of specifying a library or the framework, one simply uses the flag "-undefined dynamic_lookup". The symbols will be resolved at runtime when the extension module loads. Fixes bug #352: Thanks to Robert Kern Reviewer: Hugo Parente Lima Luciano Wolf --- CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8c831763..dab1888b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,7 @@ if(MSVC) set(CMAKE_CXX_FLAGS "/Zc:wchar_t- /GR /EHsc /DWIN32 /D_WINDOWS /D_SCL_SECURE_NO_WARNINGS") else() if(CMAKE_HOST_UNIX) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fvisibility=hidden -Wno-strict-aliasing") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fvisibility=hidden -Wno-strict-aliasing") endif() set(CMAKE_CXX_FLAGS_DEBUG "-g") option(ENABLE_GCC_OPTIMIZATION "Enable specific GCC flags to optimization library size and performance. Only available on Release Mode" 0) @@ -83,6 +83,9 @@ else() set(SBK_PYTHON_LIBRARIES ${PYTHON_LIBRARIES}) add_definitions("-DNDEBUG") endif() +if(APPLE) + set(SBK_PYTHON_LIBRARIES "-undefined dynamic_lookup") +endif() if (BUILD_TESTS) From 35bc65d8edc6db5c484e1accafda5787dadfbbf9 Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Tue, 21 Sep 2010 17:21:50 -0300 Subject: [PATCH 024/564] Fixes generator to actually use extra includes declared for global enums. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And also for class/namespace enums. Reviewed by Luciano Wolf Reviewed by Renato Araújo --- generator/cppgenerator.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 2df2bae9..afa1746e 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -170,6 +170,8 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl //Extra includes s << endl << "// Extra includes" << endl; QList includes = metaClass->typeEntry()->extraIncludes(); + foreach (AbstractMetaEnum* cppEnum, metaClass->enums()) + includes.append(cppEnum->typeEntry()->extraIncludes()); qSort(includes.begin(), includes.end()); foreach (Include inc, includes) s << inc.toString() << endl; @@ -3533,6 +3535,16 @@ void CppGenerator::finishGeneration() s << include; s << endl; + //Extra includes + s << endl << "// Extra includes" << endl; + QList includes; + foreach (AbstractMetaEnum* cppEnum, globalEnums()) + includes.append(cppEnum->typeEntry()->extraIncludes()); + qSort(includes.begin(), includes.end()); + foreach (Include inc, includes) + s << inc.toString() << endl; + s << endl; + TypeSystemTypeEntry* moduleEntry = reinterpret_cast(TypeDatabase::instance()->findType(packageName())); CodeSnipList snips; if (moduleEntry) From 681d7d560c45ecb64eb92adfc20b411e87900a30 Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Mon, 20 Sep 2010 19:13:07 -0300 Subject: [PATCH 025/564] Updated type system file for test binding to use nested types. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of the awkward: We now use the proper: Reviewed by Luciano Wolf Reviewed by Renato Araújo --- tests/samplebinding/typesystem_sample.xml | 64 +++++++++++++---------- 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 88cf7689..0706355a 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -65,32 +65,32 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + @@ -113,18 +113,17 @@ - - - - - + + - - + + + + @@ -227,7 +226,9 @@ - + + + @@ -309,9 +310,10 @@ - - - + + + + @@ -367,6 +369,7 @@ + @@ -609,7 +612,10 @@ - + + + + @@ -955,7 +961,9 @@ - + + + @@ -973,6 +981,8 @@ + + From c2ec991687e11c94e3389bc6349b1844af7efe9f Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 23 Sep 2010 16:18:19 -0300 Subject: [PATCH 026/564] Removed not used doc files. Reviewer: Marcelo Lira Luciano Wolf --- doc/_static/.gitignore | 0 doc/conf.py.in | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 doc/_static/.gitignore diff --git a/doc/_static/.gitignore b/doc/_static/.gitignore deleted file mode 100644 index e69de29b..00000000 diff --git a/doc/conf.py.in b/doc/conf.py.in index e81c9c67..18d84e2a 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -125,7 +125,7 @@ html_theme_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_themes'] # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_static'] +#html_static_path = ['@CMAKE_CURRENT_SOURCE_DIR@/_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. From 874d046ce200be7bb0f815a54dcba39909481001 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 24 Sep 2010 10:35:58 -0300 Subject: [PATCH 027/564] Fix bug#386 - "NUL, SOH, and other characters in generated code" Reviewer: Luciano Wolf Marcelo Lira --- generator/cppgenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index afa1746e..7f9c865c 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2894,7 +2894,7 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu enumValueText += enumValue->name(); #ifdef AVOID_PROTECTED_HACK } else { - enumValueText += enumValue->value(); + enumValueText += QString::number(enumValue->value()); } #endif From a94524af29c3d74960935de44a4b20fd4d5eddad Mon Sep 17 00:00:00 2001 From: renatofilho Date: Fri, 24 Sep 2010 11:24:43 -0300 Subject: [PATCH 028/564] Use a auxiliar pointer to do the things faster. Reviewer: Hugo Parente Lima Luciano Wolf --- libshiboken/basewrapper.cpp | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 0e079464..7f674c9c 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -166,12 +166,13 @@ SbkBaseWrapperType SbkBaseWrapper_Type = { { { void removeParent(SbkBaseWrapper* child) { - if (!child->parentInfo->parent) + ParentInfo* pInfo = child->parentInfo; + if (!pInfo || !pInfo->parent) return; - ChildrenList& oldBrothers = child->parentInfo->parent->parentInfo->children; + ChildrenList& oldBrothers = pInfo->parent->parentInfo->children; oldBrothers.remove(child); - child->parentInfo->parent = 0; + pInfo->parent = 0; Py_DECREF(child); } @@ -198,8 +199,6 @@ void setParent(PyObject* parent, PyObject* child) bool parentIsNull = !parent || parent == Py_None; SbkBaseWrapper* parent_ = reinterpret_cast(parent); SbkBaseWrapper* child_ = reinterpret_cast(child); - if (!child_->parentInfo) - child_->parentInfo = new ParentInfo; if (!parentIsNull) { if (!parent_->parentInfo) @@ -210,7 +209,8 @@ void setParent(PyObject* parent, PyObject* child) return; } - bool hasAnotherParent = child_->parentInfo->parent && child_->parentInfo->parent != parent_; + ParentInfo* pInfo = child_->parentInfo; + bool hasAnotherParent = pInfo && pInfo->parent && pInfo->parent != parent_; //Avoid destroy child during reparent operation Py_INCREF(child); @@ -221,7 +221,9 @@ void setParent(PyObject* parent, PyObject* child) // Add the child to the new parent if (!parentIsNull) { - child_->parentInfo->parent = parent_; + if (!pInfo) + pInfo = child_->parentInfo = new ParentInfo; + pInfo->parent = parent_; parent_->parentInfo->children.push_back(child_); Py_INCREF(child_); } @@ -231,15 +233,16 @@ void setParent(PyObject* parent, PyObject* child) static void _destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent) { - if (removeFromParent && obj->parentInfo->parent) + ParentInfo* pInfo = obj->parentInfo; + if (removeFromParent && pInfo && pInfo->parent) removeParent(obj); - ChildrenList::iterator it = obj->parentInfo->children.begin(); - for (; it != obj->parentInfo->children.end(); ++it) { + ChildrenList::iterator it = pInfo->children.begin(); + for (; it != pInfo->children.end(); ++it) { SbkBaseWrapper*& child = *it; _destroyParentInfo(child, false); Py_DECREF(child); } - delete obj->parentInfo; + delete pInfo; obj->parentInfo = 0; } From 2e715ed74316704cba426e99ba7fe06ace038ed4 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Fri, 24 Sep 2010 11:25:41 -0300 Subject: [PATCH 029/564] Created unit test to unsafe parent (parent created from c++) Reviewer: Hugo Parente Lima Luciano Wolf --- tests/libsample/objecttype.cpp | 14 ++++++ tests/libsample/objecttype.h | 5 ++ .../ownership_invalidate_parent_test.py | 9 +++- tests/samplebinding/typesystem_sample.xml | 5 ++ tests/samplebinding/unsafe_parent_test.py | 49 +++++++++++++++++++ 5 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 tests/samplebinding/unsafe_parent_test.py diff --git a/tests/libsample/objecttype.cpp b/tests/libsample/objecttype.cpp index c1407d23..e4fce71e 100644 --- a/tests/libsample/objecttype.cpp +++ b/tests/libsample/objecttype.cpp @@ -25,6 +25,7 @@ #include #include #include +#include using namespace std; @@ -269,3 +270,16 @@ int ObjectType::callId() const return m_call_id; } + +void ObjectType::callVirtualCreateChild() +{ + ObjectType* fake_parent = new ObjectType(); + ObjectType* fake_child = createChild(fake_parent); + assert(fake_child->isPython()); + delete fake_parent; +} + +ObjectType* ObjectType::createChild(ObjectType* parent) +{ + return new ObjectType(parent); +} diff --git a/tests/libsample/objecttype.h b/tests/libsample/objecttype.h index b09b402e..bb7787e4 100644 --- a/tests/libsample/objecttype.h +++ b/tests/libsample/objecttype.h @@ -102,6 +102,11 @@ class LIBSAMPLE_API ObjectType void setObject(const Null&); int callId() const; + //Function used to create a parent from C++ + virtual bool isPython() { return false; } + void callVirtualCreateChild(); + virtual ObjectType* createChild(ObjectType* parent); + private: ObjectType(const ObjectType&); ObjectType& operator=(const ObjectType&); diff --git a/tests/samplebinding/ownership_invalidate_parent_test.py b/tests/samplebinding/ownership_invalidate_parent_test.py index b99951c4..509bfcf4 100644 --- a/tests/samplebinding/ownership_invalidate_parent_test.py +++ b/tests/samplebinding/ownership_invalidate_parent_test.py @@ -38,19 +38,24 @@ def testInvalidateParent(self): '''Invalidate parent should invalidate children''' parent = ObjectType.create() child1 = ObjectType(parent) + child1.setObjectName("child1") child2 = ObjectType.create() + child2.setObjectName("child2") child2.setParent(parent) grandchild1 = ObjectType(child1) + grandchild1.setObjectName("grandchild1") grandchild2 = ObjectType.create() + grandchild2.setObjectName("grandchild2") grandchild2.setParent(child2) bbox = BlackBox() bbox.keepObjectType(parent) # Should invalidate the parent self.assertRaises(RuntimeError, parent.objectName) - self.assertRaises(RuntimeError, child1.objectName) + # some children still valid they are wrapper classes + self.assertEqual(child1.objectName(), "child1") self.assertRaises(RuntimeError, child2.objectName) - self.assertRaises(RuntimeError, grandchild1.objectName) + self.assertEqual(grandchild1.objectName(), "grandchild1") self.assertRaises(RuntimeError, grandchild2.objectName) if __name__ == '__main__': diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 0706355a..ccf9c512 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -208,6 +208,11 @@ + + + + + diff --git a/tests/samplebinding/unsafe_parent_test.py b/tests/samplebinding/unsafe_parent_test.py new file mode 100644 index 00000000..cb0e4326 --- /dev/null +++ b/tests/samplebinding/unsafe_parent_test.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# This file is part of the Shiboken Python Bindings Generator project. +# +# Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +# +# Contact: PySide team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# version 2.1 as published by the Free Software Foundation. Please +# review the following information to ensure the GNU Lesser General +# Public License version 2.1 requirements will be met: +# http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +# # +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +'''Test cases for ...''' + +import sys +import unittest + +from sample import ObjectType + +class DerivedObjectType(ObjectType): + def isPython(self): + return True + + def createChild(self, parent): + return DerivedObjectType(parent) + +class ParentTest(unittest.TestCase): + + def testUunsafeParent(self): + o = DerivedObjectType() + o.callVirtualCreateChild() + +if __name__ == '__main__': + unittest.main() + From 2177dc5fded5e4251bbc1a3793b5a8e77dbc20fd Mon Sep 17 00:00:00 2001 From: renatofilho Date: Fri, 24 Sep 2010 16:06:48 -0300 Subject: [PATCH 030/564] Created a new rule to parent ownership. In the new rule if the child object is a Shiboken wrapper class, the object is not invalidade during the parent destructions, the binding manager will wait for object destructor to invalidade the wrapper. Reviewer: Hugo Parente Lima Luciano Wolf --- generator/cppgenerator.cpp | 2 +- libshiboken/basewrapper.cpp | 24 +++++++++++++++++--- libshiboken/basewrapper_p.h | 4 +++- libshiboken/bindingmanager.cpp | 40 ++++++++++++++++++++++++++++++++++ libshiboken/bindingmanager.h | 4 ++++ 5 files changed, 69 insertions(+), 5 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 7f9c865c..cd7f14ec 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -425,7 +425,7 @@ void CppGenerator::writeDestructorNative(QTextStream &s, const AbstractMetaClass { Indentation indentation(INDENT); s << wrapperName(metaClass) << "::~" << wrapperName(metaClass) << "()" << endl << '{' << endl; - s << INDENT << "BindingManager::instance().invalidateWrapper(this);" << endl; + s << INDENT << "BindingManager::instance().destroyWrapper(this);" << endl; s << '}' << endl; } diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 7f674c9c..6e8848bb 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -173,6 +173,11 @@ void removeParent(SbkBaseWrapper* child) ChildrenList& oldBrothers = pInfo->parent->parentInfo->children; oldBrothers.remove(child); pInfo->parent = 0; + + if (pInfo->hasWrapperRef) { + Py_DECREF(child); + pInfo->hasWrapperRef = false; + } Py_DECREF(child); } @@ -220,6 +225,7 @@ void setParent(PyObject* parent, PyObject* child) removeParent(child_); // Add the child to the new parent + pInfo = child_->parentInfo; if (!parentIsNull) { if (!pInfo) pInfo = child_->parentInfo = new ParentInfo; @@ -236,11 +242,22 @@ static void _destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent) ParentInfo* pInfo = obj->parentInfo; if (removeFromParent && pInfo && pInfo->parent) removeParent(obj); + ChildrenList::iterator it = pInfo->children.begin(); for (; it != pInfo->children.end(); ++it) { SbkBaseWrapper*& child = *it; - _destroyParentInfo(child, false); - Py_DECREF(child); + + // keep this, the wrapper still alive + if (!SbkBaseWrapper_containsCppWrapper(obj) && + SbkBaseWrapper_containsCppWrapper(child) && + child->parentInfo) { + child->parentInfo->parent = 0; + child->parentInfo->hasWrapperRef = true; + SbkBaseWrapper_setOwnership(child, false); + } else { + _destroyParentInfo(child, false); + Py_DECREF(child); + } } delete pInfo; obj->parentInfo = 0; @@ -248,7 +265,7 @@ static void _destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent) void destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent) { - BindingManager::instance().invalidateWrapper(obj); + BindingManager::instance().destroyWrapper(obj); _destroyParentInfo(obj, removeFromParent); } @@ -490,6 +507,7 @@ void deallocWrapper(PyObject* pyObj) if (SbkBaseWrapper_hasParentInfo(pyObj)) destroyParentInfo(sbkObj); + clearReferences(sbkObj); Py_XDECREF(sbkObj->ob_dict); diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h index e1a9a0e7..1357c89a 100644 --- a/libshiboken/basewrapper_p.h +++ b/libshiboken/basewrapper_p.h @@ -131,11 +131,13 @@ typedef std::list ChildrenList; struct ParentInfo { /// Default ctor. - ParentInfo() : parent(0) {} + ParentInfo() : parent(0), hasWrapperRef(false) {} /// Pointer to parent object. SbkBaseWrapper* parent; /// List of object children. ChildrenList children; + /// has internal ref + bool hasWrapperRef; }; /** diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index 596e7ba0..47fd77d7 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -102,8 +102,12 @@ static void showWrapperMap(const WrapperMap& wrapperMap) struct BindingManager::BindingManagerPrivate { WrapperMap wrapperMapper; Graph classHierarchy; + bool destroying; + + BindingManagerPrivate() : destroying(false) {} void releaseWrapper(void* cptr); void assignWrapper(PyObject* wrapper, const void* cptr); + }; void BindingManager::BindingManagerPrivate::releaseWrapper(void* cptr) @@ -245,14 +249,32 @@ void BindingManager::invalidateWrapper(SbkBaseWrapper* wrapper) { if (!wrapper || ((PyObject*)wrapper == Py_None) || !SbkBaseWrapper_validCppObject(wrapper)) return; + + // skip this if the object is a wrapper class and this is not a destructor call + if (SbkBaseWrapper_containsCppWrapper(wrapper) && !m_d->destroying) { + ParentInfo* pInfo = wrapper->parentInfo; + // this meaning the object has a extra ref and we will remove this now + if (pInfo && pInfo->hasWrapperRef) { + delete pInfo; + wrapper->parentInfo = 0; + Py_XDECREF((PyObject*) wrapper); + } + return; + } + SbkBaseWrapper_setValidCppObject(wrapper, false); SbkBaseWrapper_setOwnership(wrapper, false); + // If it is a parent invalidate all children. if (SbkBaseWrapper_hasParentInfo(wrapper)) { ChildrenList::iterator it = wrapper->parentInfo->children.begin(); + bool parentDestroying = m_d->destroying; + m_d->destroying = false; for (; it != wrapper->parentInfo->children.end(); ++it) invalidateWrapper(*it); + m_d->destroying = parentDestroying; } + releaseWrapper(reinterpret_cast(wrapper)); } @@ -263,6 +285,24 @@ void BindingManager::invalidateWrapper(const void* cptr) invalidateWrapper(iter->second); } +void BindingManager::destroyWrapper(const void* cptr) +{ + WrapperMap::iterator iter = m_d->wrapperMapper.find(cptr); + if (iter != m_d->wrapperMapper.end()) { + m_d->destroying = true; + invalidateWrapper(iter->second); + m_d->destroying = false; + } +} + +void BindingManager::destroyWrapper(SbkBaseWrapper* wrapper) +{ + m_d->destroying = true; + invalidateWrapper(wrapper); + m_d->destroying = false; +} + + void BindingManager::transferOwnershipToCpp(SbkBaseWrapper* wrapper) { if (wrapper->parentInfo) diff --git a/libshiboken/bindingmanager.h b/libshiboken/bindingmanager.h index d6985ccc..2f486829 100644 --- a/libshiboken/bindingmanager.h +++ b/libshiboken/bindingmanager.h @@ -64,6 +64,10 @@ class LIBSHIBOKEN_API BindingManager void addClassInheritance(SbkBaseWrapperType* parent, SbkBaseWrapperType* child); SbkBaseWrapperType* resolveType(void* cptr, SbkBaseWrapperType* type); + + /// Called by wrapper destructor + void destroyWrapper(const void* cptr); + void destroyWrapper(SbkBaseWrapper* wrapper); private: ~BindingManager(); // disable copy From 43bd25e442557d825b66d979ea9460edede442f4 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Wed, 29 Sep 2010 11:02:40 -0300 Subject: [PATCH 031/564] Implement support to object list on ownserhsip functions. Reviewer: Marcelo Lira Luciano Wolf --- generator/cppgenerator.cpp | 34 +++++++++++++++++++++++++--------- libshiboken/basewrapper.cpp | 16 ++++++++++++++-- libshiboken/basewrapper.h | 5 ++++- libshiboken/basewrapper_p.h | 4 ++++ libshiboken/bindingmanager.cpp | 16 ++++++++++++++++ libshiboken/bindingmanager.h | 11 ++--------- 6 files changed, 65 insertions(+), 21 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index cd7f14ec..8e805ea7 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -29,6 +29,7 @@ #include #include +// utiliy functions inline CodeSnipList getConversionRule(TypeSystem::Language lang, const AbstractMetaFunction *function) { CodeSnipList list; @@ -50,7 +51,6 @@ inline CodeSnipList getConversionRule(TypeSystem::Language lang, const AbstractM return list; } -// utiliy functions inline CodeSnipList getReturnConversionRule(TypeSystem::Language lang, const AbstractMetaFunction *function, const QString& inputName, @@ -73,6 +73,17 @@ inline CodeSnipList getReturnConversionRule(TypeSystem::Language lang, return list; } +inline AbstractMetaType* getTypeWithoutContainer(AbstractMetaType* arg) +{ + if (arg && arg->typeEntry()->isContainer()) { + AbstractMetaTypeList lst = arg->instantiations(); + // only support containers with 1 type + if (lst.size() == 1) + return lst[0]; + } + return arg; +} + CppGenerator::CppGenerator() : m_currentErrorCode(0) { @@ -1778,20 +1789,25 @@ QString CppGenerator::argumentNameFromIndex(const AbstractMetaFunction* func, in pyArgName = QString("self"); *wrappedClass = func->implementingClass(); } else if (argIndex == 0) { - if (func->type()) { + AbstractMetaType* returnType = getTypeWithoutContainer(func->type()); + if (returnType) { pyArgName = PYTHON_RETURN_VAR; - *wrappedClass = classes().findClass(func->type()->typeEntry()->name()); + *wrappedClass = classes().findClass(returnType->typeEntry()->name()); } else { ReportHandler::warning("Invalid Argument index on function modification: " + func->name()); } } else { int realIndex = argIndex - 1 - OverloadData::numberOfRemovedArguments(func, argIndex - 1); - *wrappedClass = classes().findClass(func->arguments().at(realIndex)->type()->typeEntry()->name()); - if (argIndex == 1 - && OverloadData::isSingleArgument(getFunctionGroups(func->implementingClass())[func->name()])) - pyArgName = QString("arg"); - else - pyArgName = QString("pyargs[%1]").arg(argIndex - 1); + AbstractMetaType* argType = getTypeWithoutContainer(func->arguments().at(realIndex)->type()); + + if (argType) { + *wrappedClass = classes().findClass(argType->typeEntry()->name()); + if (argIndex == 1 + && OverloadData::isSingleArgument(getFunctionGroups(func->implementingClass())[func->name()])) + pyArgName = QString("arg"); + else + pyArgName = QString("pyargs[%1]").arg(argIndex - 1); + } } return pyArgName; } diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 6e8848bb..189e211c 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -35,7 +35,6 @@ namespace Shiboken static void SbkBaseWrapperType_dealloc(PyObject* pyObj); static PyObject* SbkBaseWrapperType_TpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds); -static std::list splitPyObject(PyObject* pyObj); static void incRefPyObject(PyObject* pyObj); static void decRefPyObjectlist(const std::list &pyObj); @@ -659,7 +658,7 @@ bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType) return true; } -static std::list splitPyObject(PyObject* pyObj) +std::list splitPyObject(PyObject* pyObj) { std::list result; if (PySequence_Check(pyObj)) { @@ -693,6 +692,19 @@ static void decRefPyObjectlist(const std::list &lst) } } +void SbkBaseWrapper_setOwnership(SbkBaseWrapper* pyobj, bool owner) +{ + pyobj->hasOwnership = owner; +} + +void SbkBaseWrapper_setOwnership(PyObject* pyobj, bool owner) +{ + std::list objs = splitPyObject(pyobj); + std::list::const_iterator it; + for(it=objs.begin(); it != objs.end(); it++) + SbkBaseWrapper_setOwnership(reinterpret_cast(*it), owner); +} + } // namespace Shiboken diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 96f9ad82..2440a98c 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -190,7 +190,6 @@ LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctor #define SbkBaseWrapper_instanceDict(pyobj) (((Shiboken::SbkBaseWrapper*)pyobj)->ob_dict) #define SbkBaseWrapper_setInstanceDict(pyobj,d) (((Shiboken::SbkBaseWrapper*)pyobj)->ob_dict = d) #define SbkBaseWrapper_hasOwnership(pyobj) (((Shiboken::SbkBaseWrapper*)pyobj)->hasOwnership) -#define SbkBaseWrapper_setOwnership(pyobj,o) (((Shiboken::SbkBaseWrapper*)pyobj)->hasOwnership = o) #define SbkBaseWrapper_hasParentInfo(pyobj) (((Shiboken::SbkBaseWrapper*)pyobj)->parentInfo) #define SbkBaseWrapper_containsCppWrapper(pyobj) (((Shiboken::SbkBaseWrapper*)pyobj)->containsCppWrapper) #define SbkBaseWrapper_setContainsCppWrapper(pyobj,o)(((Shiboken::SbkBaseWrapper*)pyobj)->containsCppWrapper = o) @@ -238,6 +237,10 @@ LIBSHIBOKEN_API void deallocWrapperWithPrivateDtor(PyObject* self); LIBSHIBOKEN_API bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr); LIBSHIBOKEN_API void setErrorAboutWrongArguments(PyObject* args, const char* funcName, const char** cppOverloads); +/// Support sequence protocol +LIBSHIBOKEN_API void SbkBaseWrapper_setOwnership(PyObject* pyobj, bool owner); +LIBSHIBOKEN_API void SbkBaseWrapper_setOwnership(SbkBaseWrapper* pyobj, bool owner); + } // namespace Shiboken #endif // BASEWRAPPER_H diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h index 1357c89a..20476d3a 100644 --- a/libshiboken/basewrapper_p.h +++ b/libshiboken/basewrapper_p.h @@ -28,6 +28,10 @@ namespace Shiboken { +/** + * Utility function uset to transform PyObject which suppot sequence protocol in a std::list + **/ +std::list splitPyObject(PyObject* pyObj); struct SbkBaseWrapperType; diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index 47fd77d7..36a5abc7 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -245,6 +245,15 @@ PyObject* BindingManager::getOverride(const void* cptr, const char* methodName) return 0; } + +void BindingManager::invalidateWrapper(PyObject* pyobj) +{ + std::list objs = splitPyObject(pyobj); + std::list::const_iterator it; + for(it=objs.begin(); it != objs.end(); it++) + invalidateWrapper(reinterpret_cast(*it)); +} + void BindingManager::invalidateWrapper(SbkBaseWrapper* wrapper) { if (!wrapper || ((PyObject*)wrapper == Py_None) || !SbkBaseWrapper_validCppObject(wrapper)) @@ -302,6 +311,13 @@ void BindingManager::destroyWrapper(SbkBaseWrapper* wrapper) m_d->destroying = false; } +void BindingManager::transferOwnershipToCpp(PyObject* wrapper) +{ + std::list objs = splitPyObject(wrapper); + std::list::const_iterator it; + for(it=objs.begin(); it != objs.end(); it++) + transferOwnershipToCpp(reinterpret_cast(*it)); +} void BindingManager::transferOwnershipToCpp(SbkBaseWrapper* wrapper) { diff --git a/libshiboken/bindingmanager.h b/libshiboken/bindingmanager.h index 2f486829..cec4a78f 100644 --- a/libshiboken/bindingmanager.h +++ b/libshiboken/bindingmanager.h @@ -47,21 +47,14 @@ class LIBSHIBOKEN_API BindingManager /// Invalidate the Python wrapper and removes the relations from C++ pointers to the Python wrapper. void invalidateWrapper(SbkBaseWrapper* wrapper); /// Convenience method to call invalidateWrapper with a properly cast SbkBaseWrapper. - inline void invalidateWrapper(PyObject* wrapper) - { - invalidateWrapper(reinterpret_cast(wrapper)); - } + void invalidateWrapper(PyObject* wrapper); /// Convenience method to invalidate the Python wrapper for a C++ wrapped object. Do nothing if C++ pointer has no Python wrapper. void invalidateWrapper(const void* cptr); /// Transfers the ownership of a Python wrapper to C++. void transferOwnershipToCpp(SbkBaseWrapper* wrapper); /// Convenience method to call transferOwnershipToCpp with a properly cast SbkBaseWrapper. - inline void transferOwnershipToCpp(PyObject* wrapper) - { - transferOwnershipToCpp(reinterpret_cast(wrapper)); - } - + void transferOwnershipToCpp(PyObject* wrapper); void addClassInheritance(SbkBaseWrapperType* parent, SbkBaseWrapperType* child); SbkBaseWrapperType* resolveType(void* cptr, SbkBaseWrapperType* type); From 811a59ebe7be053d0c637310ba197b4e804677ef Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 28 Sep 2010 18:25:01 -0300 Subject: [PATCH 032/564] All type inherited from Containers are iterables. --- generator/cppgenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 8e805ea7..26fea059 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2268,7 +2268,7 @@ bool CppGenerator::supportsSequenceProtocol(const AbstractMetaClass* metaClass) } const ComplexTypeEntry* baseType = metaClass->typeEntry()->baseContainerType(); - if (baseType && (reinterpret_cast(baseType)->type() == ContainerTypeEntry::ListContainer)) + if (baseType && baseType->isContainer()) return true; return false; From 385c5799cacd75523a1456cc28c05cade2b11ea5 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 28 Sep 2010 19:16:56 -0300 Subject: [PATCH 033/564] Optimize TypeResolver::getType function to avoid strcpy and misses on typeresolver hash. Reviewer: Luciano Wolf Marcelo Lira --- libshiboken/typeresolver.cpp | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/libshiboken/typeresolver.cpp b/libshiboken/typeresolver.cpp index e69f7f8d..d1439ef8 100644 --- a/libshiboken/typeresolver.cpp +++ b/libshiboken/typeresolver.cpp @@ -116,22 +116,25 @@ PyTypeObject* TypeResolver::pythonType() TypeResolver::Type TypeResolver::getType(const char* name) { - std::string typeName(name); - int len = typeName.size() - 1; - if (len > 1) { - if (typeName[len] == '*') - typeName.erase(len, 1); - - TypeResolver *resolver = TypeResolver::get(typeName.c_str()); - if (resolver) - return TypeResolver::ValueType; - - typeName += '*'; - resolver = TypeResolver::get(typeName.c_str()); - if (resolver) - return TypeResolver::ObjectType; + int len = strlen(name); + bool isObjTypeName = name[len - 1] == '*'; + if (TypeResolver::get(name)) { + // great, we found the type in our first attempt! + return isObjTypeName ? ObjectType : ValueType; + } else { + // Type not found... let's copy the string. + std::string typeName; + typeName.reserve(len + 2); + if (isObjTypeName) + typeName.erase(len - 1, 1); + else + typeName += '*'; + isObjTypeName = !isObjTypeName; + + if (TypeResolver::get(typeName.c_str())) + return isObjTypeName ? ObjectType : ValueType; + else + return UnknownType; } - - return TypeResolver::UnknownType; } From dcf1b0969fc4e5fc7c92232140ac1d1d751905a2 Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Thu, 30 Sep 2010 10:54:30 -0300 Subject: [PATCH 034/564] Shiboken avoids generating code for private enums. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed by Luciano Wolf Reviewed by Renato Araújo --- generator/cppgenerator.cpp | 16 +++++++++++----- generator/headergenerator.cpp | 9 ++++++--- tests/libsample/abstract.h | 10 +++++++++- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 26fea059..da15c4d4 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -385,7 +385,7 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl foreach (AbstractMetaEnum* cppEnum, metaClass->enums()) { - if (cppEnum->isAnonymous()) + if (cppEnum->isAnonymous() || cppEnum->isPrivate()) continue; bool hasFlags = cppEnum->typeEntry()->flags(); @@ -3326,8 +3326,11 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m s << INDENT << "PyObject* enum_item;" << endl << endl; } - foreach (const AbstractMetaEnum* cppEnum, metaClass->enums()) + foreach (const AbstractMetaEnum* cppEnum, metaClass->enums()) { + if (cppEnum->isPrivate()) + continue; writeEnumInitialization(s, cppEnum); + } if (metaClass->hasSignals()) writeSignalInitialization(s, metaClass); @@ -3591,7 +3594,7 @@ void CppGenerator::finishGeneration() s << "// Enum definitions "; s << "------------------------------------------------------------" << endl; foreach (const AbstractMetaEnum* cppEnum, globalEnums()) { - if (cppEnum->isAnonymous()) + if (cppEnum->isAnonymous() || cppEnum->isPrivate()) continue; writeEnumDefinition(s, cppEnum); s << endl; @@ -3674,8 +3677,11 @@ void CppGenerator::finishGeneration() s << INDENT << "PyObject* enum_item;" << endl << endl; } - foreach (const AbstractMetaEnum* cppEnum, globalEnums()) - writeEnumInitialization(s, cppEnum); + foreach (const AbstractMetaEnum* cppEnum, globalEnums()) { + if (cppEnum->isPrivate()) + continue; + writeEnumInitialization(s, cppEnum); + } // Register primitive types on TypeResolver s << INDENT << "// Register primitive types on TypeResolver" << endl; diff --git a/generator/headergenerator.cpp b/generator/headergenerator.cpp index 095febb7..f9384d58 100644 --- a/generator/headergenerator.cpp +++ b/generator/headergenerator.cpp @@ -281,8 +281,11 @@ void HeaderGenerator::writeTypeIndexDefine(QTextStream& s, const AbstractMetaCla if (!metaClass->typeEntry()->generateCode()) return; writeTypeIndexDefineLine(s, metaClass->typeEntry(), idx); - foreach (const AbstractMetaEnum* metaEnum, metaClass->enums()) + foreach (const AbstractMetaEnum* metaEnum, metaClass->enums()) { + if (metaEnum->isPrivate()) + continue; writeTypeIndexDefineLine(s, metaEnum->typeEntry(), idx); + } } void HeaderGenerator::finishGeneration() @@ -321,7 +324,7 @@ void HeaderGenerator::finishGeneration() macrosStream << "// Macros for type check" << endl; foreach (const AbstractMetaEnum* cppEnum, globalEnums()) { - if (cppEnum->isAnonymous()) + if (cppEnum->isAnonymous() || cppEnum->isPrivate()) continue; includes << cppEnum->typeEntry()->include(); writeTypeConverterDecl(convDecl, cppEnum->typeEntry()); @@ -338,7 +341,7 @@ void HeaderGenerator::finishGeneration() includes << classType->include(); foreach (const AbstractMetaEnum* cppEnum, metaClass->enums()) { - if (cppEnum->isAnonymous()) + if (cppEnum->isAnonymous() || cppEnum->isPrivate()) continue; EnumTypeEntry* enumType = cppEnum->typeEntry(); includes << enumType->include(); diff --git a/tests/libsample/abstract.h b/tests/libsample/abstract.h index 7a9f3e09..bbe39efa 100644 --- a/tests/libsample/abstract.h +++ b/tests/libsample/abstract.h @@ -30,12 +30,20 @@ class ObjectType; class LIBSAMPLE_API Abstract { +private: + enum PrivateEnum { + PrivValue0, + PrivValue1, + PrivValue2 = PrivValue1 + 2 + }; public: enum PrintFormat { Short, Verbose, OnlyId, - ClassNameAndId + ClassNameAndId, + DummyItemToTestPrivateEnum1 = Abstract::PrivValue1, + DummyItemToTestPrivateEnum2 = PrivValue2, }; enum Type { From 9f05e7d6b625c738f96f16d02f27f93bb1c3fbd9 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 30 Sep 2010 17:33:26 -0300 Subject: [PATCH 035/564] Fix bug#267 - "Provide human-readable object strings (__repr__)" Reviewer: Luciano Wolf Marcelo Lira --- generator/cppgenerator.cpp | 23 +++++++++++++++++++++++ generator/cppgenerator.h | 1 + 2 files changed, 24 insertions(+) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index da15c4d4..15f30afa 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2371,6 +2371,10 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* if (m_tpFuncs.contains(func->name())) m_tpFuncs[func->name()] = cpythonFunctionName(func); } + if (m_tpFuncs["__repr__"] == "0" + && metaClass->hasToStringCapability()) { + m_tpFuncs["__repr__"] = writeReprFunction(s, metaClass); + } // class or some ancestor has multiple inheritance const AbstractMetaClass* miClass = getMultipleInheritingClass(metaClass); @@ -3880,4 +3884,23 @@ void CppGenerator::writeStdListWrapperMethods(QTextStream& s, const AbstractMeta s << endl << "}" << endl; } +QString CppGenerator::writeReprFunction(QTextStream& s, const AbstractMetaClass* metaClass) +{ + QString funcName = cpythonBaseName(metaClass) + "__repr__"; + s << "extern \"C\"" << endl; + s << '{' << endl; + s << "static PyObject* " << funcName << "(PyObject* pyObj)" << endl; + s << '{' << endl; + s << INDENT << "QBuffer buffer;" << endl; + s << INDENT << "buffer.open(QBuffer::ReadWrite);" << endl; + s << INDENT << "QDebug dbg(&buffer);" << endl; + s << INDENT << "dbg << "; + writeToCppConversion(s, metaClass, "pyObj"); + s << ';' << endl; + s << INDENT << "buffer.close();" << endl; + s << INDENT << "return PyString_FromFormat(\"<" << metaClass->package() << ".%s at %p>\", buffer.data().constData(), pyObj);" << endl; + s << '}' << endl; + s << "} // extern C" << endl << endl;; + return funcName; +} diff --git a/generator/cppgenerator.h b/generator/cppgenerator.h index b4d68dc4..3869b1bc 100644 --- a/generator/cppgenerator.h +++ b/generator/cppgenerator.h @@ -190,6 +190,7 @@ class CppGenerator : public ShibokenGenerator // Write default implementations for sequence protocol void writeStdListWrapperMethods(QTextStream& s, const AbstractMetaClass* metaClass); + QString writeReprFunction(QTextStream& s, const AbstractMetaClass* metaClass); // Maps special function names to function parameters and return types // used by CPython API in the sequence protocol. From 645ab74a7d87b845c375cff83c432107a512efc5 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Fri, 1 Oct 2010 16:49:00 -0300 Subject: [PATCH 036/564] Implement generation support to target conversion. Reviewer: Luciano Wolf Marcelo Lira --- generator/cppgenerator.cpp | 41 ++++++++++++++++++++++++++++++++++- generator/cppgenerator.h | 1 + generator/headergenerator.cpp | 6 ++--- libshiboken/conversions.h | 4 ++++ 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 15f30afa..1c320184 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -123,6 +123,23 @@ QList CppGenerator::filterGroupedOperatorFunctions(con return results.values(); } +void CppGenerator::writeToPythonFunction(QTextStream& s, const AbstractMetaClass* metaClass) +{ + s << "PyObject* SbkToPythonFunc(PyObject* self)" << endl; + s << "{" << endl; + s << INDENT << metaClass->qualifiedCppName() << "* cppSelf = Shiboken::Converter<" << metaClass->qualifiedCppName() << "* >::toCpp(self);" << endl; + s << INDENT << "PyObject* pyResult = Shiboken::PythonConverter<" << metaClass->qualifiedCppName() << " >::transformToPython(cppSelf);" << endl; + s << INDENT << "if (PyErr_Occurred() || !pyResult) {" << endl; + { + Indentation indentation(INDENT); + s << INDENT << INDENT << "Py_XDECREF(pyResult);" << endl; + s << INDENT << INDENT << "return 0;" << endl; + } + s << INDENT << "}" << endl; + s << INDENT << "return pyResult;" << endl; + s << "}" << endl; +} + /*! Function used to write the class generated binding code on the buffer \param s the output buffer @@ -211,6 +228,12 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl s << endl; } + // python conversion rules + if (metaClass->typeEntry()->hasTargetConversionRule()) { + s << "// Python Conversion" << endl; + s << metaClass->typeEntry()->conversionRule() << endl; + } + if (shouldGenerateCppWrapper(metaClass)) { s << "// Native ---------------------------------------------------------" << endl; s << endl; @@ -289,6 +312,12 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl } } + //ToPython used by Python Conversion + if (metaClass->typeEntry()->hasTargetConversionRule()) { + writeToPythonFunction(s, metaClass); + md << INDENT << "{\"toPython\", (PyCFunction)SbkToPythonFunc, METH_NOARGS}," << endl; + } + QString className = cpythonTypeName(metaClass).replace(QRegExp("_Type$"), ""); // Write single method definitions @@ -806,7 +835,6 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun s << INDENT << "const QMetaObject* metaObject;" << endl; } - s << INDENT << "SbkBaseWrapper* sbkSelf = reinterpret_cast(self);" << endl; if (metaClass->isAbstract() || metaClass->baseClassNames().size() > 1) { @@ -852,12 +880,22 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun writeArgumentsInitializer(s, overloadData); } + bool hasPythonConvertion = metaClass->typeEntry()->hasTargetConversionRule(); + if (hasPythonConvertion) { + s << INDENT << "// Try python conversion rules" << endl; + s << INDENT << "cptr = Shiboken::PythonConverter< " << metaClass->qualifiedCppName() << " >::transformFromPython(pyargs[0]);" << endl; + s << INDENT << "if (!cptr) {" << endl; + } + if (needsOverloadId) writeOverloadedFunctionDecisor(s, overloadData); writeFunctionCalls(s, overloadData); s << endl; + if (hasPythonConvertion) + s << INDENT << "}" << endl; + s << INDENT << "if (PyErr_Occurred() || !Shiboken::setCppPointer(sbkSelf, Shiboken::SbkType<" << metaClass->qualifiedCppName() << " >(), cptr)) {" << endl; { Indentation indent(INDENT); @@ -3524,6 +3562,7 @@ void CppGenerator::finishGeneration() writeMethodDefinition(s_globalFunctionDef, overloads); } + foreach (const AbstractMetaClass* cls, classes()) { if (!shouldGenerate(cls)) continue; diff --git a/generator/cppgenerator.h b/generator/cppgenerator.h index 3869b1bc..55591c59 100644 --- a/generator/cppgenerator.h +++ b/generator/cppgenerator.h @@ -141,6 +141,7 @@ class CppGenerator : public ShibokenGenerator void writeSetterFunction(QTextStream& s, const AbstractMetaField* metaField); void writeRichCompareFunction(QTextStream& s, const AbstractMetaClass* metaClass); + void writeToPythonFunction(QTextStream& s, const AbstractMetaClass* metaClass); void writeEnumNewMethod(QTextStream& s, const AbstractMetaEnum* cppEnum); void writeEnumDefinition(QTextStream& s, const AbstractMetaEnum* metaEnum); diff --git a/generator/headergenerator.cpp b/generator/headergenerator.cpp index f9384d58..39db3c6e 100644 --- a/generator/headergenerator.cpp +++ b/generator/headergenerator.cpp @@ -214,7 +214,7 @@ void HeaderGenerator::writeTypeConverterDecl(QTextStream& s, const TypeEntry* ty implicitConvs << func; } bool isValueTypeWithImplConversions = type->isValue() && !implicitConvs.isEmpty(); - bool hasCustomConversion = type->hasConversionRule(); + bool hasCustomConversion = type->hasNativeConversionRule(); QString typeT = type->name() + (isAbstractOrObjectType ? "*" : ""); QString typeName = type->name(); @@ -450,7 +450,7 @@ void HeaderGenerator::finishGeneration() s << "// User defined converters --------------------------------------------" << endl; foreach (TypeEntry* typeEntry, TypeDatabase::instance()->entries()) { - if (typeEntry->hasConversionRule()) { + if (typeEntry->hasNativeConversionRule()) { s << "// Conversion rule for: " << typeEntry->name() << endl; s << typeEntry->conversionRule(); } @@ -503,7 +503,7 @@ void HeaderGenerator::writeSbkCopyCppObjectFunction(QTextStream& s, const Abstra void HeaderGenerator::writeTypeConverterImpl(QTextStream& s, const TypeEntry* type) { - if (type->hasConversionRule()) + if (type->hasNativeConversionRule()) return; QString pyTypeName = cpythonTypeName(type); diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index 142fad00..376b1aca 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -711,6 +711,10 @@ struct StdMapConverter } }; + +// class used to translate python objects to another type +template struct PythonConverter {}; + } // namespace Shiboken #endif // CONVERSIONS_H From dc044d7fa9dccd444c4998b2c260a3f2ab54644f Mon Sep 17 00:00:00 2001 From: renatofilho Date: Fri, 1 Oct 2010 16:49:35 -0300 Subject: [PATCH 037/564] Unit test to target conversion. Reviewer: Luciano Wolf Marcelo Lira --- tests/libsample/sbkdate.h | 44 +++++++++++++++++++ tests/samplebinding/CMakeLists.txt | 1 + tests/samplebinding/date_conversions.h | 35 +++++++++++++++ tests/samplebinding/date_test.py | 53 +++++++++++++++++++++++ tests/samplebinding/global.h | 1 + tests/samplebinding/typesystem_sample.xml | 7 +++ 6 files changed, 141 insertions(+) create mode 100644 tests/libsample/sbkdate.h create mode 100644 tests/samplebinding/date_conversions.h create mode 100644 tests/samplebinding/date_test.py diff --git a/tests/libsample/sbkdate.h b/tests/libsample/sbkdate.h new file mode 100644 index 00000000..e41ed1fe --- /dev/null +++ b/tests/libsample/sbkdate.h @@ -0,0 +1,44 @@ +/* + * This file is part of the Shiboken Python Binding Generator project. + * + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SBKDATE_H +#define SBKDATE_H + +#include "libsamplemacros.h" + +class LIBSAMPLE_API SbkDate +{ +public: + SbkDate(int d, int m, int y) : m_d(d), m_m(m), m_y(y) {} + + inline int day() const { return m_d; } + inline int month() const { return m_m; } + inline int year() const { return m_y; } + +private: + int m_d; + int m_m; + int m_y; +}; + +#endif // SBKDATE_H + diff --git a/tests/samplebinding/CMakeLists.txt b/tests/samplebinding/CMakeLists.txt index 2de6deea..04be3040 100644 --- a/tests/samplebinding/CMakeLists.txt +++ b/tests/samplebinding/CMakeLists.txt @@ -16,6 +16,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/base6_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/blackbox_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/bucket_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/collector_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/sbkdate_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/derived_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/derived_someinnerclass_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/echo_wrapper.cpp diff --git a/tests/samplebinding/date_conversions.h b/tests/samplebinding/date_conversions.h new file mode 100644 index 00000000..ef459114 --- /dev/null +++ b/tests/samplebinding/date_conversions.h @@ -0,0 +1,35 @@ +namespace Shiboken { +template <> +struct PythonConverter +{ + static bool isPythonConvertible(PyObject* pyObj) + { + if (!PyDateTimeAPI) + PyDateTime_IMPORT; + + return PyDate_Check(pyObj); + } + + static SbkDate* transformFromPython(PyObject* obj) + { + if (isPythonConvertible(obj)) { + int day = PyDateTime_GET_DAY(obj); + int month = PyDateTime_GET_MONTH(obj); + int year = PyDateTime_GET_YEAR(obj); + return new SbkDate(day, month, year); + } + return 0; + } + + static PyObject* transformToPython(SbkDate* d) + { + if (d) { + if (!PyDateTimeAPI) + PyDateTime_IMPORT; + + return PyDate_FromDate(d->day(), d->month(), d->year()); + } + return 0; + } +}; +} diff --git a/tests/samplebinding/date_test.py b/tests/samplebinding/date_test.py new file mode 100644 index 00000000..830e8c05 --- /dev/null +++ b/tests/samplebinding/date_test.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# This file is part of the Shiboken Python Bindings Generator project. +# +# Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +# +# Contact: PySide team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# version 2.1 as published by the Free Software Foundation. Please +# review the following information to ensure the GNU Lesser General +# Public License version 2.1 requirements will be met: +# http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +# # +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +'''Test cases for python conversions types ''' + +import sys +import unittest +from datetime import date + +from sample import SbkDate + +class DateConversionTest(unittest.TestCase): + + def testConstructorWithDateObject(self): + pyDate = date(2010, 12, 12) + cDate = SbkDate(pyDate) + self.assert_(cDate.day(), pyDate.day) + self.assert_(cDate.month(), pyDate.month) + self.assert_(cDate.year(), pyDate.year) + + def testToPythonFunction(self): + cDate = SbkDate(2010, 12, 12) + pyDate = cDate.toPython() + self.assert_(cDate.day(), pyDate.day) + self.assert_(cDate.month(), pyDate.month) + self.assert_(cDate.year(), pyDate.year) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/samplebinding/global.h b/tests/samplebinding/global.h index 2e06bce5..2b8b811e 100644 --- a/tests/samplebinding/global.h +++ b/tests/samplebinding/global.h @@ -3,6 +3,7 @@ #include "bucket.h" #include "collector.h" #include "complex.h" +#include "sbkdate.h" #include "derived.h" #include "echo.h" #include "functions.h" diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index ccf9c512..4816b824 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -1143,6 +1143,13 @@ + + + + + + + From ebeaeff37cf52abbc2beed11b27949cc4d632a53 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Fri, 1 Oct 2010 18:52:00 -0300 Subject: [PATCH 038/564] Fix function name use on toPytho fucion. Reviewer: Hugo Parente Lima Luciano Wolf --- generator/cppgenerator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 1c320184..6d7008de 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -125,7 +125,7 @@ QList CppGenerator::filterGroupedOperatorFunctions(con void CppGenerator::writeToPythonFunction(QTextStream& s, const AbstractMetaClass* metaClass) { - s << "PyObject* SbkToPythonFunc(PyObject* self)" << endl; + s << "static PyObject* " << cpythonBaseName(metaClass) << "_ToPythonFunc(PyObject* self)" << endl; s << "{" << endl; s << INDENT << metaClass->qualifiedCppName() << "* cppSelf = Shiboken::Converter<" << metaClass->qualifiedCppName() << "* >::toCpp(self);" << endl; s << INDENT << "PyObject* pyResult = Shiboken::PythonConverter<" << metaClass->qualifiedCppName() << " >::transformToPython(cppSelf);" << endl; @@ -315,7 +315,7 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl //ToPython used by Python Conversion if (metaClass->typeEntry()->hasTargetConversionRule()) { writeToPythonFunction(s, metaClass); - md << INDENT << "{\"toPython\", (PyCFunction)SbkToPythonFunc, METH_NOARGS}," << endl; + md << INDENT << "{\"toPython\", (PyCFunction)" << cpythonBaseName(metaClass) << "_ToPythonFunc, METH_NOARGS}," << endl; } QString className = cpythonTypeName(metaClass).replace(QRegExp("_Type$"), ""); From 8dfabfccc24222815262ffe489bd5729e749384d Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 1 Oct 2010 18:28:38 -0300 Subject: [PATCH 039/564] Avoid possible race condition when destroying wrappers. --- libshiboken/bindingmanager.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index 36a5abc7..5149a4de 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -27,6 +27,7 @@ #include "bindingmanager.h" #include "google/dense_hash_map" #include "sbkdbg.h" +#include "gilstate.h" namespace Shiboken { @@ -259,6 +260,8 @@ void BindingManager::invalidateWrapper(SbkBaseWrapper* wrapper) if (!wrapper || ((PyObject*)wrapper == Py_None) || !SbkBaseWrapper_validCppObject(wrapper)) return; + GilState gil; // lock the gil to assure no one is changing the value of m_d->destroying + // skip this if the object is a wrapper class and this is not a destructor call if (SbkBaseWrapper_containsCppWrapper(wrapper) && !m_d->destroying) { ParentInfo* pInfo = wrapper->parentInfo; @@ -278,7 +281,7 @@ void BindingManager::invalidateWrapper(SbkBaseWrapper* wrapper) if (SbkBaseWrapper_hasParentInfo(wrapper)) { ChildrenList::iterator it = wrapper->parentInfo->children.begin(); bool parentDestroying = m_d->destroying; - m_d->destroying = false; + m_d->destroying = false; for (; it != wrapper->parentInfo->children.end(); ++it) invalidateWrapper(*it); m_d->destroying = parentDestroying; @@ -297,15 +300,13 @@ void BindingManager::invalidateWrapper(const void* cptr) void BindingManager::destroyWrapper(const void* cptr) { WrapperMap::iterator iter = m_d->wrapperMapper.find(cptr); - if (iter != m_d->wrapperMapper.end()) { - m_d->destroying = true; - invalidateWrapper(iter->second); - m_d->destroying = false; - } + if (iter != m_d->wrapperMapper.end()) + destroyWrapper(reinterpret_cast(iter->second)); } void BindingManager::destroyWrapper(SbkBaseWrapper* wrapper) { + GilState gil; m_d->destroying = true; invalidateWrapper(wrapper); m_d->destroying = false; From b5ce4ccf7c96926ed2eb5e0818ccd6b60e3bb907 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Mon, 4 Oct 2010 19:11:16 -0300 Subject: [PATCH 040/564] Remove trailing whitespaces --- generator/cppgenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 6d7008de..7db34192 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -883,7 +883,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun bool hasPythonConvertion = metaClass->typeEntry()->hasTargetConversionRule(); if (hasPythonConvertion) { s << INDENT << "// Try python conversion rules" << endl; - s << INDENT << "cptr = Shiboken::PythonConverter< " << metaClass->qualifiedCppName() << " >::transformFromPython(pyargs[0]);" << endl; + s << INDENT << "cptr = Shiboken::PythonConverter< " << metaClass->qualifiedCppName() << " >::transformFromPython(pyargs[0]);" << endl; s << INDENT << "if (!cptr) {" << endl; } From 6c7e12d9651c1017d64a104b97a7a49631fc0a82 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Mon, 4 Oct 2010 19:11:27 -0300 Subject: [PATCH 041/564] Disable generation of __repr__ function for QObjects. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Qt implamentation is not usefull to Python developers. Reviewer: Renato Araújo Luciano Wolf --- generator/cppgenerator.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 7db34192..3e4f8565 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2410,6 +2410,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* m_tpFuncs[func->name()] = cpythonFunctionName(func); } if (m_tpFuncs["__repr__"] == "0" + && !metaClass->isQObject() && metaClass->hasToStringCapability()) { m_tpFuncs["__repr__"] = writeReprFunction(s, metaClass); } From 4133eda85a6cf5b7e4e1f17c36724cda1d8c42f9 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 5 Oct 2010 10:45:25 -0300 Subject: [PATCH 042/564] Fix bug#402 - "Exceptions raised in event methods aren't printed to console until termination" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Luciano Wolf Renato Araújo --- generator/cppgenerator.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 3e4f8565..dd64dc0a 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -618,21 +618,23 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu if (!injectedCodeCallsPythonOverride(func)) { s << INDENT; s << "Shiboken::AutoDecRef " PYTHON_RETURN_VAR "(PyObject_Call(py_override, pyargs, NULL));" << endl; + + s << INDENT << "// An error happened in python code!" << endl; + s << INDENT << "if (" PYTHON_RETURN_VAR ".isNull()) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyErr_Print();" << endl; + s << INDENT << "return "; + if (type) + writeMinimalConstructorCallArguments(s, func->type()); + s << ';' << endl; + } + s << INDENT << '}' << endl; + if (type) { if (invalidateReturn) s << INDENT << "bool invalidadeArg0 = " PYTHON_RETURN_VAR "->ob_refcnt == 1;" << endl; - s << INDENT << "// An error happened in python code!" << endl; - s << INDENT << "if (" PYTHON_RETURN_VAR ".isNull()) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_Print();" << endl; - s << INDENT << "return "; - writeMinimalConstructorCallArguments(s, func->type()); - s << ';' << endl; - } - s << INDENT << '}' << endl; - if (func->type()) { s << INDENT << "// Check return type" << endl; s << INDENT << "bool typeIsValid = "; From ed8481cd7accabe1b9a88aa27101bfe13bb87a62 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Mon, 4 Oct 2010 19:16:57 -0300 Subject: [PATCH 043/564] Fixed signal registration when arguments use typedef. Fixes bug #397. Reviewer: Hugo Parente Lima Luciano Wolf --- generator/cppgenerator.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index dd64dc0a..a2186e0e 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -1991,7 +1991,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f if (func->injectedCodeSnips(CodeSnip::Any, TypeSystem::TargetLangCode).isEmpty()) { qFatal(qPrintable("No way to call \"" + func->ownerClass()->name() + "::" + func->minimalSignature() - +"\" with the modifications described in the type system file")); + + "\" with the modifications described in the type system file")); } } else if (func->isOperatorOverload()) { QString firstArg("(*" CPP_SELF_VAR ")"); @@ -3008,6 +3008,7 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaClass* metaClass) { QHash signatures; + QStringList knowTypes; foreach (const AbstractMetaFunction* cppSignal, metaClass->cppSignalFunctions()) { QString signature; @@ -3017,7 +3018,23 @@ void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaC if (i > 0) signature += ", "; AbstractMetaArgument *a = cppSignal->arguments().at(i); - signature += a->type()->cppSignature(); + AbstractMetaType* type = a->type(); + QString cppSignature = translateType(type, metaClass, Generator::ExcludeConst | Generator::ExcludeReference).trimmed(); + QString originalSignature = translateType(type, metaClass, Generator::OriginalName | Generator::ExcludeConst | Generator::ExcludeReference).trimmed(); + if (cppSignature.contains("*")) + cppSignature = cppSignature.replace("*", "").trimmed(); + + if (originalSignature.contains("*")) + originalSignature = originalSignature.replace("*", "").trimmed(); + + + if ((cppSignature != originalSignature) && !knowTypes.contains(originalSignature)) { + knowTypes << originalSignature; + s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver<" + << cppSignature << " >" + << "(\"" << originalSignature << "\");\n"; + } + signature += type->originalTypeDescription(); } } else { signature = "void"; @@ -3404,7 +3421,6 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver<" << typeName << " >" << "(\"" << typeName << "\");\n"; s << INDENT << "Shiboken::TypeResolver::createObjectTypeResolver<" << typeName << " >" << "(\"" << typeName << "*\");\n"; - QString functionSufix = (isObjectType ? "Object" : "Value"); s << INDENT << "Shiboken::TypeResolver::create" << functionSufix; s << "TypeResolver<" << typeName << " >" << "(typeid(" << typeName << ").name());\n"; From 5e982a5494a56d53dd3467e438aab6d2a7f08204 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 6 Oct 2010 18:53:33 -0300 Subject: [PATCH 044/564] Generate code compatible with new properties function names. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Renato Araújo Marcelo Lira --- generator/cppgenerator.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index a2186e0e..ef8737a2 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -3488,10 +3488,10 @@ void CppGenerator::writeSetattroFunction(QTextStream& s, const AbstractMetaClass s << "static int " << cpythonSetattroFunctionName(metaClass) << "(PyObject* self, PyObject* name, PyObject* value)" << endl; s << '{' << endl; if (usePySideExtensions()) { - s << INDENT << "Shiboken::AutoDecRef pp(PySide::qproperty_get_object(self, name));" << endl; + s << INDENT << "Shiboken::AutoDecRef pp(PySide::qpropertyGetObject(self, name));" << endl; s << INDENT << "if (!pp.isNull())" << endl; Indentation indent(INDENT); - s << INDENT << INDENT << "return PySide::qproperty_set(pp, self, value);" << endl; + s << INDENT << INDENT << "return PySide::qpropertySet(pp, self, value);" << endl; } s << INDENT << "return PyObject_GenericSetAttr(self, name, value);" << endl; s << '}' << endl; @@ -3532,7 +3532,7 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, const AbstractMetaClass s << INDENT << "if (attr && PySide::isQPropertyType(attr)) {" << endl; { Indentation indent(INDENT); - s << INDENT << "PyObject *value = PySide::qproperty_get(attr, self);" << endl; + s << INDENT << "PyObject *value = PySide::qpropertyGet(attr, self);" << endl; s << INDENT << "if (!value)" << endl; { Indentation indentation(INDENT); From 9cf34f01876807559e018ad616fc4aa2fd6ddf05 Mon Sep 17 00:00:00 2001 From: Lauro Neto Date: Thu, 7 Oct 2010 15:30:15 -0300 Subject: [PATCH 045/564] Remove uneeded flag check. Fixes #405 This check was preventing operations between two Flags. Wrong argument type now are handled in the Converter calls. Reviewer: Luciano Wolf Reviewer: Hugo Lima Reviewer: Renato Filho --- generator/cppgenerator.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index a2186e0e..b890df64 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -3280,17 +3280,6 @@ void CppGenerator::writeFlagsBinaryOperator(QTextStream& s, const AbstractMetaEn s << "PyObject* " << cpythonEnumName(cppEnum) << "___" << pyOpName << "__(PyObject* self, PyObject* arg)" << endl; s << '{' << endl; - // We need to check the type of self because self and arg can be swapped - s << INDENT << "if (" << converter << "checkType(self) && " << converter << "checkType(arg))" << endl; - s << INDENT << '{' << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_Format(PyExc_TypeError, \"unsupported operand type(s) for %s: '%s' and '%s'\", \"" - << cppOpName << "\", self->ob_type->tp_name, arg->ob_type->tp_name);" << endl; - s << INDENT << "return 0;" << endl; - } - s << INDENT << '}' << endl << endl; - s << INDENT << "return Shiboken::Converter< " << flagsEntry->originalName() << " >::toPython(" << endl; { Indentation indent(INDENT); From 6aa6cef19beaafa80eecfad4a9f15d619cb80214 Mon Sep 17 00:00:00 2001 From: Luciano Wolf Date: Fri, 8 Oct 2010 16:11:28 -0300 Subject: [PATCH 046/564] Updating documentation to reflect adoption of wikipages. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Renato Araújo --- doc/_templates/index.html | 4 - doc/compiling.rst | 22 -- doc/contents.rst | 2 - doc/tutorial/bindinglibfoo.rst | 77 ----- doc/tutorial/buildingthebinding.rst | 131 -------- doc/tutorial/globalheader.rst | 36 -- doc/tutorial/images/generatorworkings.png | Bin 37257 -> 0 bytes doc/tutorial/images/generatorworkings.svg | 392 ---------------------- doc/tutorial/introduction.rst | 32 -- doc/tutorial/libfoo.rst | 69 ---- doc/tutorial/typesystemcreation.rst | 136 -------- 11 files changed, 901 deletions(-) delete mode 100644 doc/compiling.rst delete mode 100644 doc/tutorial/bindinglibfoo.rst delete mode 100644 doc/tutorial/buildingthebinding.rst delete mode 100644 doc/tutorial/globalheader.rst delete mode 100644 doc/tutorial/images/generatorworkings.png delete mode 100644 doc/tutorial/images/generatorworkings.svg delete mode 100644 doc/tutorial/introduction.rst delete mode 100644 doc/tutorial/libfoo.rst delete mode 100644 doc/tutorial/typesystemcreation.rst diff --git a/doc/_templates/index.html b/doc/_templates/index.html index 47d4914c..076f3bd3 100644 --- a/doc/_templates/index.html +++ b/doc/_templates/index.html @@ -13,8 +13,6 @@

Documentation

for a complete overview

-

Documentation

support for python sequence protocol

- diff --git a/doc/compiling.rst b/doc/compiling.rst deleted file mode 100644 index 2b4f8c8b..00000000 --- a/doc/compiling.rst +++ /dev/null @@ -1,22 +0,0 @@ -Compiling ---------- - -Getting the sources -^^^^^^^^^^^^^^^^^^^ - -* Download URL: http://www.pyside.org/downloads/ - -Build requirements -^^^^^^^^^^^^^^^^^^ - -+ CMake >= 2.6.0 -+ Python >= 2.5, but < 3.0 -+ Qt4 libraries and development headers >= 4.5 (4.6 recommended) -+ api-extractor + generator runner - -Building and installing -^^^^^^^^^^^^^^^^^^^^^^^ - -To build and install just follow the generic cmake instructions in -section `cmake-primer `_. - diff --git a/doc/contents.rst b/doc/contents.rst index f7fb39b8..6292e952 100644 --- a/doc/contents.rst +++ b/doc/contents.rst @@ -5,10 +5,8 @@ Table of contents :maxdepth: 3 faq.rst - tutorial/introduction.rst commandlineoptions.rst typesystemvariables.rst codeinjectionsemantics.rst sequenceprotocol.rst ownership.rst - compiling.rst diff --git a/doc/tutorial/bindinglibfoo.rst b/doc/tutorial/bindinglibfoo.rst deleted file mode 100644 index b12e53f0..00000000 --- a/doc/tutorial/bindinglibfoo.rst +++ /dev/null @@ -1,77 +0,0 @@ -.. highlight:: xml - -.. _gentut-bindinglibfoo: - -Binding libfoo using Shiboken -============================= - -In order to create bindings for a library based on Qt4 a number of components -must be available on the system. - - + Qt4 library (with headers and pkg-config .pc files for development -- the - ``-dev`` packages in a Debian distribution). - + Qt4 Python bindings made with :program:`shiboken`. - + Typesystems for the Qt4 Python bindings. - + Headers for the library to be bound. - -With the items listed above the developer must write the components from -where the generator will gather information to create the binding source code. - - + Typesystem file describing the way the binding must be done. - + **global.h** including all the **libfoo** headers and defining required macros. - + A build system to direct the process of generating, compiling and linking the - binding. - -The directory structure for the binding project could be something like the tree -shown below: - -:: - - foobinding/ - |-- data/ - `-- module_dir/ - `-- glue/ - - -The **data** directory should contain the **global.h** and the typesystem -file. This typesystem need to refer to the ones used to create the Qt4 bindings, -commonly located on **/usr/share/PySide/typesystem**, the exact location -can be checked with pkg-config: - -:: - - $ pkg-config pyside --variable=typesystemdir - - -The **module_dir** directory is the place where the sources generated should -be placed. It starts empty except for the build instructions file (Makefile, -Makefile.am, CMakeLists.txt, etc). The realname of this directory must be the -same written in the typesystem file: - -:: - - - - -If there is any need for handwritten source code longer than a couple of lines, -making them unconfortable to be put on the typesystem xml file, the sources -could be orderly placed in a **glue** directory, also referred in the -new binding typesystem. - -When writing the typesystem file (more on this later) there is no need to refer -to the other required typesystem files with absolute paths, the locations where -they can be found could be passed to the generator through a command line -option (``--typesystem-paths=PATH1:PATH2:[...]``) or the environment variable -**TYPESYSTEMPATH**. - -For **libfoo** no glue code will be needed so this directory is not used, -the other directories are created with proper names. - -:: - - foobinding/ - |-- data/global.h - | `-- typesystem_foo.xml - `-- foo/ - `-- Makefile - diff --git a/doc/tutorial/buildingthebinding.rst b/doc/tutorial/buildingthebinding.rst deleted file mode 100644 index d03010ca..00000000 --- a/doc/tutorial/buildingthebinding.rst +++ /dev/null @@ -1,131 +0,0 @@ -.. _gentut-buildingthebinding: - -Building The Binding -==================== - -As mentioned before the build system used must perform the following tasks -in the correct order: - - + Gather data about locations of headers and external needed typesystems. - + Run the generator with the correct parameters. - + Compile and link the binding. - -The first and last are the usual, being the second the only novelty in the -process. - -Running the Generator ---------------------- - -The generator is called with the following parameters and options: - -:: - - $ generatorrunner --generatorSet=shiboken \ - global_headers.h \ - --include-paths=$(PATHS_TO_HEADERS)) \ - --typesystem-paths=$(PATHS_TO_TYPESYSTEMS) \ - --output-directory=. \ - typesystem.xml - -Notice that the variables for include and typesystem paths could be determined -at build time with the pkg-config tool. - -Collecting information with pkg-config -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The Qt4 bindings include compile and build information through the pkg-config -mechanism. The pkg-config name for Qt4 Python bindings is **pyside** and a -simple ``pkg-config pyside --cflags --libs`` will retrieve the information -needed to build the new binding. - -The Qt4 bindings file ``pyside.pc`` for the use of pkg-config requires -the ``.pc`` files from Qt4 to be installed. If the library is in an unusual -location, e.g. ``/opt/qt46``, remember to export it to the ``PKG_CONFIG_PATH`` -environment variable. -For example: ``export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/opt/qt46/lib/pkgconfig`` - -There is a vital information also available through pkg-config: -the **typesystemdir** variable. It is used like this: -``pkg-config pyside --variable=typesystemdir`` This provides information -where to find the typesystem files used to create the Qt4 bindings, and as said -before the binding being created needs this to complement its own binding -information for the generation proccess. - -Makefile --------- - -Below is a plain Makefile for the binding project. - -**foobinding/foo/Makefile** -:: - - LIBFOO_DIR = ../../libfoo - LIBS = `python-config --libs` \ - -lpyside \ - -lfoo -L$(LIBFOO_DIR) - CXXFLAGS = -I/usr/share/qt4/mkspecs/linux-g++ -I. \ - -I$(LIBFOO_DIR) \ - -I`pkg-config --variable=includedir pyside`/QtCore/ \ - -I`pkg-config --variable=includedir QtCore` \ - -I`pkg-config --variable=includedir QtGui` \ - -I`pkg-config --variable=includedir QtCore`/.. \ - -I`python-config --includes` \ - `pkg-config pyside --cflags` \ - `pkg-config shiboken --cflags` - - QT4TYPESYSTEM_DIR = "/usr/share/PySide/typesystem/" - QT4HEADER_DIRS = `pkg-config --variable=includedir QtCore`:`pkg-config --variable=includedir QtCore`/.. - - SOURCES = foo_module_wrapper.cpp math_wrapper.cpp - OBJECTS = foo_module_wrapper.o math_wrapper.o - - all: generate compile link - - generate: - generatorrunner --generatorSet=shiboken \ - ../data/global.h \ - --include-paths=$(LIBFOO_DIR):$(QT4HEADER_DIRS):/usr/include \ - --typesystem-paths=../data:$(QT4TYPESYSTEM_DIR) \ - --output-directory=.. \ - ../data/typesystem_foo.xml - - compile: $(SOURCES) - g++ -Wall -fPIC -DPIC $(CXXFLAGS) -c foo_module_wrapper.cpp - g++ -Wall -fPIC -DPIC $(CXXFLAGS) -c math_wrapper.cpp - - link: - g++ -shared -Wl,-soname,foo.so -o foo.so $(LIBS) $(OBJECTS) - - test: - LD_LIBRARY_PATH=$(LIBFOO_DIR):$LD_LIBRARY_PATH python -c \ - "import PySide.QtCore; import foo; print dir(foo); m = foo.Math(); print \"5 squared is %d\" % m.squared(5)" - - clean: - rm -rf *.o *.so *.?pp *.log *.h - -Keep in mind that the Makefile above expects the ``libfoo`` and -``foobinding`` directories to be in the same level in the directory -hierarchy, remember to change any path references accordingly if -you choose to change things. - -Testing the Binding -------------------- -Now compile the binding with ``make``: - -:: - - $ cd foobinding/foo - $ make - -To test if the new binding is working (it can pass the build phase but still -blow up at runtime) start up a Python terminal and import it by the name. - -:: - - $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/libfoo/shared/object/dir - $ export PYTHONPATH=$PYTHONPATH:/path/to/foo/python/module/file/dir - $ python - >> import foo - >> print dir(foo) - >> m = foo.Math() - >> print m.squared(5) diff --git a/doc/tutorial/globalheader.rst b/doc/tutorial/globalheader.rst deleted file mode 100644 index 7e853f8c..00000000 --- a/doc/tutorial/globalheader.rst +++ /dev/null @@ -1,36 +0,0 @@ -.. highlight:: cpp - -.. _gentut-globalheader: - -The Global Header -================= - -Besides the information provided by the typesystem, the generator needs to -gather more data from the library headers containing the classes to be exposed -in Python. If there is a header that include all the others (or just one, as is -the case of **libfoo**) this could be passed directly to the generator. - -If such a file is not available, or only a subset of the library is desired, or -if some flags must be defined before parsing the library headers, then a -``global.h`` file must be provided. - -The use of a ``global.h`` file is preferred if some macros must be defined -before the parser gather data from the headers. For example, if ``NULL`` is not -defined and it is used as a default paramater for some constructor or method, -the parser will not recognize it. - -To solve this create a ``global.h`` including all the desired headers and the -defined (and undefined) flags as follows: - -**foobinding/data/global.h** -:: - - #undef QT_NO_STL - #undef QT_NO_STL_WCHAR - - #ifndef NULL - #define NULL 0 - #endif - - #include - diff --git a/doc/tutorial/images/generatorworkings.png b/doc/tutorial/images/generatorworkings.png deleted file mode 100644 index d35a565ffc8795a85f6ddfdb69a89bc1d62af7e1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37257 zcmXtf1ymeM*X`i$?hYZiySo#D1$PMU?(P~axP{;l+}#owAh^2(cbC`P@BOUBqPywt zsi|YN_pTGAsw{(oNQejmfl%aRCDlM6$RrR50u3G(xI$QyXAb;23wfr|vLQrfPc9V}cujGfIv9v&XdU+ryNOpP7QnH`)hvrYvG zK_GIFoTQk#XZG=`rO{^%BDnK6xxbwM)_kVZe%-CLo1alYZi%XjZsMqh2g7fPexnZ# zCjWU%5gchN`FpKI^lr_^Y~{*dR*vX9E+W&{KUYuUXRZ5dPb;94X%2#Y;!t#Pc#2T< z(2+@q|Be#BMUqV+i{w9g}ew2tU7^ElRp{{jla!n zt_o{GMlDU&p^J}P{n|%u1+UEB3Ha(y09VxXRWap0t|I!dicU$x_@qt+WdsY;97II7$8l#Ft z3ck#3AdwX`gDD4ZRp%rw%XfOYY(XFx(xswKDYBPmGklyH9v^}(o~zaPyqO9A}VfM`kACkc0V`JFXt1lCcg`x5|vV%wnF`A|u^& zY$i>7s$z@ffhRo0&KHd=GE~I1Vv23Mbr@nI4&P}|N3J;+Vht<;i|Q{a3eiIpu>I+` zUswV7{FG`g1LszY!n3E!V&VbcgLI@;TG|nK71ffqT42||cQJUqMHiS-h9+8mV*14i zb0!#gfxytSJjdqB$d%WOywXk|_yf5L?gRRD>o=0u-;Coce}k|OXmi3^5PvV0y_`X;Ig1kiYBnF6-&fes9Q)w1mG zM%@>mB68!vxPooZ%!NMXogeOZUA;BBg#5UGD}4x|O+s8N5y7JMgE+OZ8R50&v7w^v z;DPb&u?&w7RX6-H@@)jVmFmRlbqgjxcZ%R93iO|eam**FlP{V$Kr%WX3w{#>U7Xf@ z*f=!-Citd7;l^i`yCVm%ujiLc#68ptLGZ$))B9NQ8KczC*RXnh+_`414EZ}6;XF&j z!cjxiRl+(Z!T8_$@#PuTmUc4E(-@EJR4 zd1Iq*VuXp=s^7!>GTZhG&eArAWp#n&UD?P43pA+s zheaW9%p34(p%JDkbn(a?xD1kr5G%*SQ6GyW`h@w_DjU;FTz1?fgT~)eRG>#mN23`H zB~J37^TUagyfdtFUKe7c4hZxC`(w7SA5Iy4rUs5U*Pg7tg`^CAfR)L_34IWoAR(DD zeAy@D2Ib~a^DW3O3)ZOv0oi1csY`cmS?jl~p12{JIFt?TSrC_)99 zLVTx9R(emQgjuc)uy0QU!U#Bqdq!mMQWHo!1N#GBk-&W6s7K-8oUE@CVG)DI```dp zuivWKy#5Gu%6ihPZMhkjVAd6+sDa)POQ$mfYG^Uh{&2VRx#C_{jue}kZeKp=Qe}hQ z>pSVq`4btZ(-k*pm_`X(Tg1cJJMm_FCRY=LR-zy%IIz*>w}RSQ)~Z64{(;VDdqwLH zu#b&}{2SMIqVQ$L$egr)$1bFVPi{|G$MWuk5Rp>(ce8lN`pyf;D20TGeC~3^&vK_P z{>=3+UEPTnu?DQ&WpLlvbZ~EeHZ$8HXHns(c0O!3+{`n@GyeKDyrV;$@xc~Lhm$Pf z_*n4d<}J59C;{&|P;1yfn6F+-44wB^{gvbPke_1KqgxrT$lJ5!bK8p*4s9Zc+~sFq z78a0;cW8|BPq8$a{I^lN9Em(mUr~8H;IMH&UOWyAW(e8fz@q&tpDx75$_YImd8z&N z(LmZ^J*dXmT1POHo|&7#zpKB_ecXQR!7;l@uRv9tHieSWgv^Y6oOSXM#rJ$V0nTY} zjLY?~IMeW3T3VP;yUIokOR2_H(E%ixAb99;K93vniG9JrVTWH-T z%NFt>2@0}nypfJSEK3oE3@j@{{`&Pxi=P0pT+~<93YeLyqbOkVzIlW15&Rkvs6m_# z26#-mbNxdoPmOXrb4(EwxG`+Ev%(q|<)P~3DDD0|HlHbA1b=>IP2iRxHuSY`;`O?DxaRe$=oOuvxcrF$l`rx zX}XpZbwcOvSG~c_cs>15;aiyEvUXQ$EVm?h>4h%Y=rw%)zKVrWQK!F&cpQX#hLPsB z`x9u%Ii7f{SMOnl<7>jx(>Zwe`P~LhFpAZR)Fw#z%IVD5>6>1hp)J9B{hf)j9b8`> z%{y=@W~Dt9@o}qkBm4TqB_e=Xe*bPvNpvcDL(ec+jl;tUhOi(`TlLbFqdw9hND!^^ zF7NeK=n~~882$1BE)YjN6$H8KgrPG)^ z4dygvQc8MUa37?$u693oiS&o_OUiF(u|WB%zobNRu|4=u`^1}U#v=@4G7{_I{5L6o zQxelMVN>N{kUk^vF7WqAYQFwp{n&_jF?umF0uHRt;W(~5`CVC|`mw<~|@ViE` z8iyJN0bW$wn%f^=G9X){7#vbxE;Xw9b{Gl$P$CQKPB7@X++Ch*v~l6IKh`~UTWxC& zjfz5E_pK+n+Ut%7{K{x_ODXXWLzBT(v0O-<_pEYgsN`0ADo5VF#)!h0to4A%t8?!v z1PPq`>MwsAs@5pI#X_a4`}|(9DJU6K#oDGuO`!+o34#zw$g(8trZjH&L;TS51;=B) zCK(@LL0V)GdLCxN1H(QAKO1Z?`L{L|zr4o`UQf#Jv(qHjzwYi0DxdsvZat^Blz1_G zA=_Wq!a9NlwKH{%=Xu&eAl2w{H;-F9L*+q38Rni6D3M>0^!$)AyUNs};Rk%)W!*_vqw?+?m{UcC%dxVsV-D`EaxSOSRZRc(H9P*h zEm3na-#0fMuc=^jn0;20(2#E#qM6@mBR3+x#V*hH@myeV z)6zE28gb-(3$`P8bIZEMMc>G1ncbr;liQE_hcZzR+@0yh?uni?#+8g4;7ngEvaK5f z??csNNvGSR=ffF)sQxTbTtIM{Rws$D8|H`{oBk^`Rg)x-|^8h0a zLVqP+vA9|qPt%=q_-bWqTWP&qrewQb;Ai@Xa*|HXlXNt(mn)&?O#CY7CtEtUJg)oX z1~}HiVl`cdUWbu`X~Ojw=SoaR0-1YNgjyN&J~2acO&=Or4a*h5a7coLJ)?}@IxK5y zCON-Y3Vv>fr@U^dQW3Xj$r(d!-7hg`9rixcey7tVKD%ZPklCKuR=Z)>w0mkhUyF(4 z#)tdXr>&ZRx4u`bCkPOb1vW-nsQ|w(=E>d2>IH!USOQuW+R26aAhNX{Wfb5kX636C zDH(n*mK-~&>>9`RPP{EzKK4VM-kP^|T*Ei}@Au;|1~R zW1)=G*IfFKw56x6($&j*;z10#rnxJ>f(dar=SC;$DbMRhz~5nW7_<$;2&` zf82U5F-$k;Pre$ww!EBklS+O~J6ZC#(#@2k2915^Me zaDiq80ba|GSQmKfAcSBLn2&c~u}U)p>3gx}MmB;q7jTNs%Zo?;GfZut^KKg*`le`~ zb-W&W$ZM(-=JkM2>h5E?p{p`c&0fpTT#x~_<>(RFtlzcrpj%AxMd6*dtFmsM3-tia zZ6oe5I zq(fCt%|KBJzs`1r56+)X9pjTRv8L1`(YsmmP~Wh!gG3M&FsO_7A)zj&1x?1rt@zoZ z9k$E|)kLs73%yJge1XduK20MrlMAl7HE@RotbdT@x#kl ztYGJpLWV5k7JH^*iCUTD>&^3L@0&B6RR`_v&_Gx>7l@4x$GIlaFREYJGJY#cpRP3ko(f%q9?)znWd38Ol`?^=lLR+LpP3%rP_}nx6Lk;?ER~j*^BoPW-D+!RBRK(b$#b%lEq?w=c z$tN-j&ygAMm~xBjnq99CHg=HoJZYvYflfd7NkCYw^zqq3v7N(rLbF$6O4kz@&K}Og za}&*5XIBB+_V@aNk-mWkp;jju!`aWojBj3iIy}}Wt#!oin(pun)^Xnm<)#`n=AH9w z)P|CU_I}{1;P3#BOAGJ}YDjvmj)Nw)-CFG~;Hfr=ql_LgzrrW9qr8Ky(@Sy92mgiv z6)&~FpIt4K?(ElzsGhJ@1l#d2bm;3w;&$;D+{j_wN#H>vEMvpfMeXNTL3t2XI&?)_ zRG;PepiT>xh-ITy68{@V104;pNT(sIl}Hk_S;|- zx@8Z$yifYWTLeT$)kWU#rr5RU)i#NxdL!-4sTG)biJk4P4)2T;;^#hsw-m69l%&L$ zlRv|!NwE%3a*+O1!naJA(`WYht=! zxp1D_1umo6LxD&og?i32`zca>Hz0*ue#_8*VWixmtUbFIwq0n1FsZ`_mNK#v;6Sx6 zf?`ACy*Q*`QV=JWlK}!@NL9cyBnUnZe()Hl-k6djNSj*P-Jt2VttoCVSFCC)Z24cC&kY8=gW29f>as`Be zHJ_5TtpYX0fTID~Gk^FE@ed()rFjPN(kX0?h}=hId;osN9d~gF4rzl+-0O+Xj;GYV2xBIax4uvdBaVME5OT zMb%oOWj6Sx@W<$p)m3d<{*oU|QnnMnr9lH}+?L61^WPSNgO)>%jiUJv?bqJREl>F| zQM%B?bg3#iN?Df?n4V2NN!AXgU;TykPHs-sKdb5J;9fc-<+k9O85dwqeL^_DVKC?rq@ck0lG*C$`YWiU8pkZJZX zwpm4Tdy(mxYs1s@ziU^{A)7l3X+HvawxLOO27apjbr94_Ru!gG)tO+ zj>eYLL}V9cu%;V3=+I5BCB zN7UV)_ctzGEiQT;{PkkTH(jVdLkg8S9;{s4X0^PvKE8j+Xv%GDt)GwpfXWwro*pw4Aj#M9>z9n@2l7p2IK97tA^E8n>p}MUc~EQd8$C|=@Z{l+Ybxp=i4XC zCDRhMu-I!`=o`BP@0-qsvt7ga?N$*6@#`dZQw{E4e4IXcSWro#h1{;lK!js(2}d1^ z1}+L@lfk6QSjJ2J&klodyAIw;YNat$jQMu z4U;^aK|!9;=N=f54W^K2H@U6U;C0y}ghe|IhJX?fqh$!7uoTbLAlb_z>O1|=(VB3P zVv|x%3F$+D)Q=@DYtE*MS*EEzmqThurS_5Q?_xR+4Ih-Ww27n?&B4sowR3oBItR2E z$P`%uc3j$1Qjk{hASMu`!rQ)Jdi6u(e4=hkbNu?+7KqXG=-%OFseNAHd1kPCN$z5` zA5}}+A?p3z6~k&@%f+x4K5IS|_j4^-jnX}KTH22cE+1lxG2d4jRgl=j4*!n135<;f zsxu;lD&|*NL z%lyBYt6QhuvJ|ZzzWHj7Qq>Pmug^*iHd-Cw+1=f607>=nE^`+nMhc(5lIWcYYiM9( ze7%-==b#J-mf_;#xmCKvS}zS3ELE&g!J*>nqt#10|LPzmWJKX9aEue9xUy*mI(}NB zkWE1~+Y1e>3DGI!D9DXMgEDk8`W6=8KWbbg7B4sVqZ3!Qqv&?~lO$$m2Vv1M+x$T# zN*T=D0zujd>#?52IWN6vdCMstRTULiwP;<0!5?Emc(k#Q+EFp;&{! zS1A6%PeuGABO^m4F+fVPiSmQ%3I^yHSmfhSwEfDV-9H{lz_3gM;EJ?r=31P#gKiCq zhOdVJz6fJx-w&B^g&a1i-#vV*YhJoWY63 zpMuI`^sOKBG&N10EZ?;`SgwIOoV$@!QzJwr<_*~!KPq%PdNenGQ5|VJzhl)S55&vS(1hf;)f(9;p?|? z&J*B`;&1GjMS%6cfBoZq_cbIw=Q|}04b=L(s%|;tZ8&YLX_4O{Qii$p3wP6G3J2lC1er-uAp|G3wu1;AI_dW?c{uX zBxs}qqE)!8w%R+Lz@4+pUuQj!&)C8)^X}y@m#<6XdCXQd@V)HUpNP zoB~`VhA)4OO2V>WE;o+z z;gl$gVYHJVJR-Hp8ng|4GPKCsAF%R|IaelY4=P>3=;GyMA^zGgf zy~mKfSOLa;3_*cW1rp^n>L3B<)cWqVL z+{hM$r%#4DW7FSaBhk}DYNSYD9`;j1^w1ByQA0 zy{WvyI!O{T5L*u>d>!-*3;Us`INxG4T1~e13Yi3&qA^I8dM{iDG7eqbI@mfzQdk+W z8YHR!oFa<@{0X>>29OYco7B?y1FIB%)7T&#KrJk`eUGR}Qj@w27eXvKcnb5vcct+f zJxVIuCFos;qz95}C_3cE+^nueD_`qU*zBMQTj+3G{n=WF4Ivqkicbu{i~lD^f&#-* z!>m0MFi7e->IXqR_}d$kO_Jd&U6zmFinAs+cefu10l>T7WlCt!#^%YV#I$7Ev*l{T zyW=t2x*s%vjJwk9vu0-%R~y#eshKto$ZFpPjv(=+>Ua z{>g~TUj2ycG4OBh)75URlG7q3fFUP%AF!HP&pAZh5WA_lt!w4rPvN5WpD>M9j_DLa zz}U<&siGzW?gODEh5;gbR;p3oHXB{spaCo-P{J{kul`~1g6(2YzC=w=TlE75bP(Ty zzz$z4?_baN`4DG%e|;!h_>ZdZw4gw>GHj^8eB5^gn&aad&u!}p{I?SjGvO&{uE~~I zZ zP@9B5(n_z4PSzzJMuc1t!xVy6_OHm*XIcjkAW& zPsjONzrx&@Beo*k%qQ*BY*A+5>5Qnt*Gy)!?ptMLBo0}`okmeqJ29n@;tKwZ=i=dU zCEnTHbf9X

`wuxtABtYvvg~AyBY{{o&I(EW`9v$P|~3p-z#f`}{lBtMI3sL~{41x=8_e;X`r)0vh)nEl;C5&svc{Lz-yo~#>H&M&64e~S+j1!7+u}bA$PO;bA zxLk>G%xNUzVlroJr73%KhK>aPG`{CB19%wh!i;bCX=;t%!lx2H(qT{+&g{hQeGyz9 znXFR}EyM6&bw%FUHMNFLw``3Erg8)cqdK;hW1Od?&R{2ujfs;hN>g(FXK^gsW2>Tp zAeh2G?dYdeAo`{F4$hvgmK%?|m_Ni8rAbm|8bXvLq%NJn0{>EY? z6TXTp4zSMvc;o{j_MG(3XEWt0&F$-g&%Dpec`X4{*w&40>Lhs}vWAmcQvFAdp!#8s zo23rUEy``je=|}iPW7nc8wRC&%wM!sf7Y_QA~z~&>R_@bZyRs#z;gU4H3T%^UZy~o zmIto#z5~uJ(zPJ@l2Dn|tp^P~bacNr+Spig$J=t|Hydcn;`fR7C1!pPYQ|G6J7%>`trbA4ySO527@kh=Ff2-uWrkOi7*<`*Ug?B* z>VCtn@o&If4ex%LnP>7T5>Ss8_YDxPM=YAwezi9=qaHTh9`t2RvIrFwGvLPU{7a~u z`>OqG-y(JRoc(<+)TqoY%}jd-ydvW!Ps$n^8iONh;Er>Sld#i6TSl~tX-Wt_$OHUC z=lg(XWJQ>l^HW3#|HQJnKUU!L`m;)!thOR-Qf%@zoRG)vntPP)@9$A@3&Pf6)NN$< z|5-<}7d}nIPkrSs)2zTCBd8JLZe$H>%;AD=46IFLl?)B-?VZJVjeDWsNJ@Vq9laQh zL`e`cv86oDA=%hHgCT+=>U86nW>3mVsuFT{_6Q!34F;;wN~bT}Kl*%jeFsBy=3KRC$hLQEOXhI4v2FsI4TUc=cLXTnNf{H!FkF zeQE35yRKy9MKK>&1KY?QE?D z>52PfinKVWB6=H zpDG)`Yv0u5wlKYpl=spAjkK1L5b3iC3jA@B^$GI}(gW9t(d2%Nq{)ok)M7r{4EKMi zAp1`#b1>2%LP1snkvH1e)xgn$DG_GHw~u3lFCw9@}4$=bgY8XHzclXb8jQP&VXT)%UexQbCX$5#6QJ@?Vm5 zs)o9he9(QLMSR;maLk-D*SsJ2yfWS%JJ_)d)H+M(1~(UKD$u=m8J+8=H=U+4(%VW?S5*=cRc)4S^Bk7$@zTw;JVQ2ZMrZs$osbMt|#OL+H7X&9hyQ>61bDu zxX)a2ilcE7>zO)XaJpK-pdJqGt?*aiJmW^UgOoXn)A*Dap%g>g`+JR`$ilybNhP); z!Ec=<*ds*qfXkg<`S_lc=j{cF?arZZZ5+-nM7roIk>_{Eeh`Yn`{;hDVQnrKljy+3 zix;_fUi5cdur@XfR*?B?O(irA{TJ)oK%D&LyR|t$qy4Ci-rAEyoL79O1EfkoW~Q0) z*KOCQ3p)PWUD3ql0(h$9?lHhnP3Z>|eC`HY{cS2+^BD>s?iuStmRQG!r7FX?eQki_ zlakX@)5ByY?hd@|wAU2N6vG%Dc^YN&1M85u2_>M%vp6Y_xRu6e@w^6!f(_QzW9 zUU}d8t7Wy-s|3JE$eDWK;Z;PveZL{m>_sMXT`ruZ*4bVr^UWo+mzPBuF{ri-cwd*C zpnK_dym_IcEMoq}HZ>TYM_Ff#B5glff%c^6BW0ekY+ z`EGIU$hcxedjQprS@Fh7FH_6)1gYYeCXzV*gI5!ehrCWzdPKKmSt&7y;Dpmq%g#OY zC`sPyX}nsOi{P>_F3MBAp^&3}3?g@#eL@g$Z=L(Cm7d5IUF`0U^PkJu2pD&@#=Vlo z15$@^T2*S4_XohTNaCjM|=Bwi}tZ8%Ni2ye4>^gGVM7fe-v4#l;|m^ln`cy89hP z^@|VAxIp9NlOBUE1LN{7j-H?bi|+N}kCKw#$2ljP>n+S{2N#6cFyA$&Wui)fLO}cM zKnW%lE=rMXI-4#~_vlh97zkp5YZwOdqxP={mk}kd)j2z#hJGR;0||@o7PzN*%WpmR z1XvCGWb@TpKECHSw)k>3GkfeTof0B`K^FROCV&4ju_jyVd{;SH3#|I{W4koWVJjx& zjyyF}aJIAXOkc)8lOOllnKTz-90a=9q|m;#KzqL1cfac;pm@@MWT`%+Kjg>D7VBmd>}J&jx6S&^Qkh7t|7i=NNH^^}lvCTr7n*zdo|2=x z=`#>2B~kT}blB3wBKRf-V8Phfc&3!iqP+9F-Jn2++$fX4PNxlnVf}qy@2Js_2_DPg zVWGw+eX~p3!*oqRWHWL^5kC&Gb|O&cXMS*foTPvDxh7V_R7*@sjt>U3j7fs0FPa{% zUMBsfuEOnetIG$}k!qRPRqc(vfKeeQUGs)RrTS}<0?K^YhR)|!n(2cogUo36JpHDm z0TB_TAKn?J`$p2Ay8Yy6J&|y5^Shz6EuH-5#nSN6`;H}EAGrKKlRS z6TKC9@r<+h{)?*P^>IYnu}Jgu+l0+AYyF!3dLX#tM*QUFRwncRiwZH3k4?_@JtmW1 zAZ-+Z>P(x*&9QlB)ZcA$jJv)@EP-n|B}FMQgRZs3Ic57crUG`X)r){&oex*7bZFTh zt};RBL64SHp2KWg=abRtIfOOv%Y2~%kr$lI$koqI5hBvTiJaX3(-ZN`N(;S58aw+US_j& z;}`Z0@5|x|8|`CB*59gyx-Qn;s0V4S)1%qa2)3&dXdysdnOBX#nEq;dP+@7YXz{l3 zrIl+XlOGu7?p$bcQWgEuon^Fh3)tYaTSun+w74wBpFZ^$-fHOc;nfvSmK){>?aB8- zV2$8-HPw*FoYRKiIx*?}6q%ZHYMGw?nIFSXkgu_U{v`zW!xM?@jpf;1RriX<=Uif} z+nKvxE_2=aFGbKyBF!y6{Cv#fE^#sGYc`d{dgMuj5+xse5BH%0?K0W4u?G`Nm=vO> zpZmUUAC%t_3gD@9?l%4hX9!D;E5aRJT_jBuDM6y2e)hDf%$tCl$x``{?wv@x+C*5# zs>bRZ`?uJST)+zBr~bI4UAgeW{$f5WmXhTB(C&T z!*#}VyOW9?#QDfZD~OLYCbGA?GTAY@%{d^q;s$qnkTEqXs*KFGYqMGMHC3$uQf%|- zk`5igi`~hsTKnnF{@(VvL%>!i#pk@Q%{j?`$Z&S>$OS%M^$QA65w-g-d^&ARurL&H zK1@hy0gOKoI!I0-U*FT#n#uXn#U)=Q$15sS3}>bu{|pAG-EI+05^7mfp=! z?JD(nZI)hT=G$`Xp+lLkL6cOK@7Jiu;Vay|U2+zIBKh2x$eap15IGf}!P&#i{fBp> zGy+J?x){}ue=GHCjmcBFVS_os6oU5EMR{r0@Y5fQtrv>vhAO*?y?}_DysD6ZqPCH7 zu$Zq|hdcZ4jVK8Qn$tjw8&<16qvPccyg-Yo3wp7Xjg3QiIuAN($w4YUiZ65+l|Nyt z2(9TLor1PkUsE_6Sq$*X$FsekbK+p^2tQPUP_duW`Ri80LWj z{b0(CzYABKW@dlAx>UM%8|P+a&6!iElMKE~1AFdyP|VJ+8og|Lo#{>5LT_y8dndj8 zHaa^*Ns^5nNvs%|7-i(5y-+^CV6Uzetac*|jFN2ex`ju)a#3iEh9z75vdg9p_r9yV ztWLU{1J*^;7uv`2iEgg3p;7!z3$EvPlc!pIMLL79K{x!VTXcI94h-T-nc?}o-R0yk5n4`WLdqm^c2Phu7R(kA}c`{CWJ@0+Z(PE=ZdoK&b9lvv@>%Qp=7 z$Fl#iE=rCjGb77ntCA=8Uhj^dG^5!&2+XS{6(mj<)Zo!HyrOZnL88jVq&84%Lbf*4 z9q?TEIgOAk3`<~Mf*P~vX@p+mQV+|8q2Y)JH_VHVSDjPgDJi(amiXRSE>*CZTGtY- z;Zz8cFSG34e9;GeX0QS$)POH!TcE4v62BbE`W@6+kw6L*+SRzXIPbCBKYNhWZPtza z9tkaLB{FZOnS z(&s!{(6cm&jLJk9>UfI2ZBh1H)i)oj9CHIdan0pie5K~<11k5Vk0-Dp)|b#J$tf}+ zHe^8-QWs7az%fN~%d|h2IYry;X+WGulgO8t9NkQIu5>MeCiY+BHQ?s9Hs+vOe0EWR zJ)3}_8^gW2+}B({_BZ)&q82Cf-?6_PGdDp+!IK@Ikyct=iRh!~RdL-evUD>3&Dcz} z(##P*lfE4bgpW){Zgtjou5N4|1?5Wk^lEE*cVG5mMNoEIvB#%Yy?XpC)1K0Xu^&+? zG)(laYB#>x8ij8sK+cn{N=ieI+ZLFkpyR+sGDI~DiFN(h+N|FDyM!wEPH$LY6kRF~8VEFp=ZJ#O zc&5YAeCQfR+2%@;{~<}Nm_e)AMlKyUyO*(f53(63{F&{t!#_&9_#AGwnfv36W50#o zB2(J2!c_<#W}LW>CZEghzHz4!nBMDBUFQ;U8lPj;csM!*_KQZ)&87SLyn zJGYVesNPMxne8&Ppg5!r1@MEsLwq&&zvsC`V@M??yVfi2-5%h0>uiKTqLf@i`J-f} zJy|Xl*NeB+YZ-4>Un(=X5YyvNhDuD^d+|dI>*F(;eCcpwZEtt71nGe6?)&`5>sW`2 z45)`&a}V8{)3rFXV}>!0cHSnycdT`HthnSwj_QQ&W=z7frF!$%Pb?2ud@C@DA{? z2&Hz03NO#zNyGe9VA0f$a{^ukPP_98&oG|i;N%}%B1CL_@e$1G`H^S{Rgy7)(e{pXy*>Jul>cPJ~6k+7*E#D)q; z0D^cwTg$ic&N`e8HoXw06{UA+3TMu|a^4C)+lBb?9}-Bk-@P+ewcX->JwauV*;n*Z z64Zt;Mz9;7uvR@mAs|@-Qyz$C#0@m?15^mKe6F0g38Q8JE9A*jCn8UGIBQxKCEFoH z{7Vz8F%L`6cn!wVHG%m7YX$ay%|+H#8Ry#5)k5tzl2d=PW7$wain^+Wl~ymxCm(YY z(m5O(la@YQip@M`61b4s8TQ>gKX`tj1@Q$Y*E5oi&sd}6(*!!;n}+Gn58y&JpqMF< zbF+*4dcrpaXm}%3qzOeBA7?w*ycBM~!*=+xMqt&BlveqCjJcl;F{rC0{2i^QwI{lp z`SJ6HVsrehN*c9N!&1A)SsRjwzVD3n$o2D=OB+j2g~GSg0f-$4R!DTzjfR1la-L`` zMYXsu3%o|NqmrTPU6DY|+1WSi1rH*D*C5R83$&O2qvea|*wf@@N!l7K8cq~WW5g*= zSh{Z46MA=*DLMml7`|Bz z5e_N0;i!Y;@2u6kF-0ePC(FXz9f4Y4Amh1Xv(nd4gVg!KmzROX>g2Z~we112Vn~6Q z;v+Fb_*f8D$oU-m&jmm$SMf&;Ys|6@I~mrsOZ{*aosg#yhO4z=U&SnT+MhjOJ&js> z-IC*hj}k+YvTlxN-tf-#&I+kS1PaFHHV6#5HW|7a3F~fnU5y}$`7;QRqT=rTzkvzZ z_=811;S&zMZbu29j+6BhbOq~xeY|}=Q0*|#SaV6KzVv1VbH<-{A;-}RWmSq9;+!0q zU^VDDERFc-?9nJdB{g{ZgWcudrCL`Zaffdr&tv`bSboyiV%>F6*QYfvg**E=R(B1! zGr_%EKapwH!_d_Pgzh{PU@|0oL;TJ9Vqt*RB04ZT?U)yl?}9K)Mp!`+pjO3rqer3S zy#=Bu%oFiri^D^J;DZSne%uZpzxwkwS{4=bPaQqzQhL3uXR^9jU5GyyKPGa}cC6>c z6i491x}^p)ppaltgmVK6hlO@tauFV~bQMF%kw)~BRtW&>{qz_Ds;~EPw*tJESCpj5 znDz@C_;fusdyG>eqG;ZQ254P!#mBO^DS`gQj}?Sa)3{$ag4SERFgb;8VwLmg9u#02 z0O}cOmf4IW#Y##}tP~<6AcUxJS85#2EF)+MI1=uY=u1q?j$f%Hh7Se_(D^L1FBIud z+}1kP(%)q!6=1Zu?4oW_Z6|)uKtv)^Xz^|>lxwGTthsWH!9=o#7`}UhDk;48=(QmE z-aoo3=R^F$O4!V@DsJnE%s$P&d3XYQ26AXPSiv-@Ync(6AQMQ4{pJb^oY9UZmGGwI zV8TjQ)*o19@G!Ealn|W;xgs9wS?C#ikZt|W`~y&yK^{V6@AVK^{i@t315)KlW{NBf zK*)8&dH(sxL9T`~*5kQchd87u+v|c%0(5D>V6kQBWE@f_HO05-f?s|)GXM-q@tBY8 zUo5AeqeCNTvP>!k;Z*0BHtrEWLA!P?%KzKI?x@ zOpjX`yT)s4kCy)gAJy<2P6y^w+om+O{)*DNIBmCh^mi zS|yVI3kPe5!+|P1TXBR3X?|@!I*ivtizhoiVD2RsFe$U+mD98ji77HJcN%LwtAvRn zq`ExLe=wyQMPO5ZLZ)<38Ne*hQ7#xStdFf*v+1Jo-`NRGOB1F^18%xmoG#29%d|N@ za}hO$MueK4-t%d@8KD5|%e62a;NoQQStwFLg)^-i+jx$*BLuF8y3hXm2|2?<69FGI zv;bkEy_JESrv!%IAT&{-^nCdeEip40gqPTe&s8rSj07pXc1t$KXa@lT7K-=Q&SYjKG`;l( zE*(#^XZ&~XWTQhVTBuHy_|X~_tM8-Qdye)y!lmG2hLn~b!hh+m`BdY^lXK);{}&j{ zqNnG!pe^xgBDx!yS|&nxS3P_kn!V}dPJ-K^i&#(H`rO7&HJOpU9U5pvQAu<-2n(Ha zGXOn`!Sb{=UvqO}+;AIU)@mEv#O*Z+e@%a$^f`8o9KduX<`jEc{Pv98dQ6EE6_SI7jLin5z*M*E<#KA{>NC$<*&bWSM9AW z0Vl+jB>G8NsSu57LBQgwNUpRi_3~8Zax9N^o5=v~IG4GKb~X?L|BP3?cR`%qv&0TU zT2`sveu}Vj7e$A&=NN}9?PJX{HArcRTk7c4j+|?*0r{uK$CWl$q`Zz+(PhMDmlxC= z>dSox?j!0%Wm0ek=b7D%jV4*NI1GSi0y{-cn0Yk)5OxN>I2er_0X-@J<1i^lE&%O5 zK;*I(TvfzWo!cH=@)=L!)6YNv6g1{l_HHRDTnj5yY4$HjhIskBLakq zg#rK+xI~?dM7-R!T<-F6;4zdxF+#p$W?{NoYU8wjdE&etC)k}mre2xNhJEIH!9dt_ zR>joqY$7rTCJb|b8A_9B5B^0=+^r9;ZeX>X&!6$O9>MAHUJ4A2 z>!Sc}DI4t{d1U!IBS(1!nBh3?^x*E1xTEf;C#Iaqj$dUS4=F-YK}qt+nFt}003M5P z$B793A0-G-bg&@tN-cJU2!7N*hL4sdC1-17kTu@pb)NfNCzdIxX`%WI`MC=t@ILIv%2Dks>@6nPu-s_JgDsoMcj%H=PM@?DkP<+L@Y#V3wB(g zv$rDOe4m}4i$O_%z>99LR5^Z&Zz2!RF$-GGvw8NMe7QiwY#TIxC?^#V3Roy<{yj4?BH6E{1tmldl ztis&|dIa*&j^{v^RkjE)(KE|Exy|%{064%IQXZ=*P>rGwPE&l-`So2NoZ*DO37(Lb z{{!C_Alevb3+FqQ$zyY_m~4sNbZ1k5_Lt*kF3+>}&i4(98M2{krlm!nB7}KcoW7O} zd0reaueAFTa?Fzk$EXN_0z-UAuD#8_D|fDIjfnw@h7}Q~bm_{}G+Ii!T}Wf6J<{Vl z?BS^&h`bY?fA7pp%`{qQm@qQl4g@^!apfX!wVOcmmKpyNOqp|Pjzk0(o7Ij8_?`Gi zj;XYYZ-~zwo`^pfm#cvuNzoKAkXQo@O#%GHzY9PPSX0W_?-wP?THW;?Ai(S5rhWVw zaps#?)`olJuBK=mzrD9X5z%o?aN_*mUH}h8{VuG1pv6jF&#dg|<8pnYd&rybk zGh^}ZFOZJb(D~1MXyVp&{x#PTRVgGul0Vh!id#;%7b{bx1i0-ZVSOYQ1|(PH!{VyE zr0+p~S+`sFU8cLVM)F~pqX?spj!vRFYJ|?eq9e%QIIG~a99~v;%;_0F%+MwRvKdGB zqv#oQdh+T8B}RYn{Qglk3jthyrtjyu<16>hXqgXDG??0p+Fw(KE3Xw#TJL}I<{S~G zXGB7S02csiki^bQ`5VP8d%eev^fqdc_N%fX=Mg`8?#=h!#R}%Js*@?ZfgQCQhitxB zWhldtG0C^BN57%*o>J3glaX&>sklV}SMi=tSBAOTXKTCD8TWGkHZedO8+#!tO@@>7 z?M}Dw{K)uP7KJmvhE=l{yUWzobUtY*llGjK<^2<~q)y!|%2Pg|P6EV+jbjo}I{(d$ z!F0Zz%CQa~n%9?qtaX!>(Vh?Y!T@(J)Olk^ygJG6s9tt?u8YUElOtu`6%gXy>A2s= z=1O`g-FkM{ky|IQTt=ZPIR5w|_osdcM66=XEH1-HfUx(2GBt|gVQhcO9It5#D z;qZZnJdG+s(%s}w38T!rWWqlMn)DPu{~u9b85LI(Y&$@3cXxMpcMt9sBv{Y@!5s$o zFGz5Q!9#F&65QQ2xI@r)xbMF8)`DLQXZmzkm+abArSqLH=faLI@7+>9*PShE)_qr) z1*tZj=I3^@c;eIe^5>Q!|0DqtI-7@o?`K_UWmZE|N&^WSc(Xc=sl>L)j(D7m+*NH` z7Mg(?reYSdimcqs@X=p14u(ACs|Sl>^Pf#|b1u!ILchq`N36zm>zTcT6z6uq$PZnm z^_HQ=0~O!?zG~*DtxI6EVw^$NweB3_1b}T{;pFI^Je*#;?HYUVDpZjo!DqLC19%>x z&M;;Qu{7_QQlTAOa@Vh(^MW5^RV!VL?-4H_cyG=bl4!~2s@l;$9TsbDODY8z5q-4lR*O=i5>#^UkO(lN^ zK<%26o8W$hXdq<7U2waUQgV>VxW}Aj3c6NOrpQgrC`SD`lbmB*_W=-@sgenXS?8IK z=z{6mpPrIFnj|O2IZjJVz|&S=&-Gh8GULi1vM8w~qSGeP%tX6+YRT*3&mM^yMas0e}rZXX4Yaxw4U3uklC;0pz z?(0cvGB7m=^}xTd?G)CG5m^wtNh$EbGc6VGo(dMpajIZ|v=e&3BnCD@f&vlCqJK@a zrFDb6$)R}_Avi3|J;%)ltxZ^1*w=2@SAKn}Y!V+74LS957S|A%=Vp105MiRx+*+Pw z?3>EdfVp@O!NJAbT3WNAoi8t}fyqV($4WzoUa}o#YqtDs z!ag%?EmR+$?tDno_$J3^oY`iv874{ly0E^2-H6)R?pad(ef#-WsaSNbxt|pY5O;Jv z2x>2}otlKl((KK>fvx8+PQ;-k)%*L-e0I3p>ba5?HAPEq^hr< z=id2qf7P{FZC%}4|0Z^Y zezxkZVPP~fSZb*<8~9`5pOHYr0ZqK4c(hrkQS8eXoF;5H2ThSQMI$xNgXOgtvEh;5 z((bl6jciM?1tGnfxih}n&UX{Bu{}Q#m0fNZab-TpQ`~$;s3z@-W?aXn{GQs`&=J*w z7_iX=ZTNr#j9)oac#OWpwH9%w-E6aPE_`vZ470npE6IXIeP_aQW_;1pt8rat z8+&zhJz;Kb84njnR6CT^leGBD1!lbyp;wFCj3xKVx7?ev{0}zX1A=dAY|1@F0D$$A z@+UZkcVtHNdXGG!PURW+l02NsH2)EkAJz`{j-5|kYg$y z)uBA7Go1Y z`%h1U*=jYJWnk|PbKuUus(Pgb3n}PYKNaHk0KaU}(t?s;D6KThr}liLQ`p^WT2FSO zxH{!;3|aSpI44O?xSm&TL;rZrLV0fR<05KiX3K&OdesVym?$^7==f&**YKkpQoM6k z1jUAt(gKsw_j?2Q4`CK_e?mb)f^K}FLpvcOdlUk@9|mJzakGV5ERP#=an3SC>`=M5 zzq%f*qgmM;mJ4!1$L!z26N!9f()%PXgc!}Mzb&oj1ol1{jM z^;pcly}t-RNxIA3GdU>8(MZj_=ecV0+Iwcow^|ZonwGR zTG0pQTS75UJmH1FCGSe>Bdd_b{JgUM;sRo(&F#=H)Y2uLUYjQN0YDz5Sy)19%Ooh% zUGENKIb)ibMf+CQVJ!of!u^%IB1+=LR2)f?Qj%iBJS90A?1JowKh{^YZ4h@kBs`md zTlydY)V4>2RJ?4^2IWyM_GjU*T3voAe7GK}qw7A15xS~<#r_qaP8V^oq7YooYbe!q zmUE27(vAElaO3mrm6+JXRKvCVhYnG=C!Yaq z(S@2P;tE|d8TS)dTiaoJm!YBJ?sX^7-N_3fwY-PCj}M=Us*i-KDs0<5OMhMuDJBU? zT$FgFoS_e&X~!$EF&lgmCZdZQY5Y0;O;55}XJ}_9ADNh6)cU#`$Co=77E>-X-~(mn z90*V7EQ7-uSJ`AmnuJvA1BE%Eu>BT@Ck~I6C(Stzr}yMb-^Mdu=*P2KLN7c^d-lG5 zvY&>L27l8;cn;Z+%MUK(1$~+swA62ONB{X1rwewq<2YfQwAAAE2V=TGxwy6ttU%xy z85qShtWQ2*V3YEy<)bcMN78@)1;4=KSzaW5R8SlbN?X7gwn8})*0)%>%l+hJ9`cbcHd3cAn<5o?O<`_WOd49+vI8&?MQrt|0P3MTzPL~NR!$2 zEYaYknx$A{VOnA+AbZlrotz+(5zbIA-gNMl*Ow9tPtD=r$}7F@E8Y4-hwkE-_0ZfJ zM?G5(Clw3U_UO8nK>aySn5G(9l}p1^)JuO}(7kOD|G7<)pk?z5Sw zf4EuTL%1WnS@%$ZV^^MHCS9W9=ZAxS9g=lFgcgGqC7=-rDU8Xl<0&-k0Jhhr)4mBg zEhFr}C#E}lm2=_mq|*!B(?f4(jQe0eziUpuaifTWUaGsSA7COpC(|(Qr;pT|N#ee* zCl%M9*+R;gq)rPKQ{~3Ub#(pBv(%*nt2b5+(o0uA>ms(kvZ4}BOBmk$iA{(M3s;Cn zk_3_!ziv>>H70PGjy}_?W8&gcysi=N+Sv5A=Pghn1ot8nm>EVQIgI zn-dfb%2RQ25g4|@m09j}S6i^f0mMov84SQfG~e31Q#`*C{5g|?iGPP=Oh!(ZdW!=t zQl?5#N+iGyx#=fJ*Pjoq3(uAk%1O2=rlVpz!Hs1-`Q%`JuXxHdIwI$AsLX)^!#p%t zT;0h&Vpikb=_%(X@`t_r@c2z8@YCpG4j?`JA9I?c>UP?pKu`B(VU3M&aA=ybc}7j& z`V#ZAp+Fx$@}&zoV#vkoM+P=;W>~B(rXb@QuJHcLsfTHiMNPKL5SnyliG*!rHpXuK*s((QJ%H01gJ1 z5Lt1-X_lj`2EJVel1rq1UL%h%w{ea)sE??7qrN>pM?^=*CwX}iA_mGxDk@0jV*d+l zSUeIBw-Nht&c@MR~b79>r+a5p!%{e+^Sn3ze=Wp-vxs}NWjZfIfV z%U%i@4ZLqnU0^3S-*OQ=6sx3P_VuNDRu#Z1z)r-Bvg4iiD=IKr+E3*n9A;hB|ugCec< zobZk%JwPqj2ERP9o9~vLodAYChx7*%Nz=UpPz#P6Cp#2>_HNvRgA%r+(}K(i0JQ=* zncLW!n7A1T87goytzZJ-YWjd@bKdzX;Se$Z<*ldlCk7Ogz&C&LN&|lcJvMQfbFovG zqg~ebD&%J`??h#Uo-DyW&ht`Mpg<3;-M68q`LbiO-TSv-z8KC89~MeqciWJ|u+?bS z>3@`LVz35F(JiY&o_5tPt9ik=fOHA@T?pzMWJ>Ai1pVUK^Df5GnX!e~TU#d?yQEKK zMZaX6WQm=w_!-0=6BQnR+M8vtp0`F4O(>q?oRm#zRGlhvoZ%W-5=vdubu+rwZ2J6R zR}|tzhPt&sRlCXuwHL^D$5vd*=dHG(Pk!pts3+uXvQZK?ZI=5Znu%1aw2Vo!N|FZj zEKo--vZC61yl@Wq=V3s<8I|-&`SR7Fjbv{THU!GV7vT+gmelUv-Vc_8ciOG^peIzn zgKF4xPD=(f($)}eo3l?ZtzDdfJq*u}nIap>fS1+k=^WMJJ6`CS`)#r90J`0qL6=2#-YSfg~-~O*~$vZ<_4&e}4;z zcD!y5X~)fsOSL1SqQv&c$iuy_<+n!d$Wcgt5=`X67uwChsq5*5%TVbMoWX&BCE(y7 z;DW0dkGewO$t*2xZ&`Hzo0OETq+)nOi+=Q@s#dqKwmm9^<5m1u{3YHGQ}M&a-<@0> z9mK2thsrEtv(Lumu9on&wq@IQtX)_$V((}7`nZ8>+;;Z?JK)gBg7p3zesh`Eo9$=% zArtX;-}~n}{}sFNr;Spcg0kiDESuC~r!p)GTC5*$;Seq^Dwu`D>%mm#r>a{is=~wT zfDEnK11zQBSSroCqdrYP;It?)zpw*;2932 zp@X7Q9xZn-%qE8&X-J4sg1Z74-W?ym&UWqwz~6YiUtkxwSJYHI<~A$j+3h90V;&y>UukQ3PRU3_L4(&&+M`JUmHQSR_Q<;-paZ`z{TCe4FYYRorMu{M{KW~1Onl?`-MH6mezouE)1McPrbC3i1#xQCg$bj z)KpkZ1?dl-B=)7NvpKk$4U&O+8%YJ_5pYfp-g2X3QElyhhmglj&yFi6unpnYB_(i? z@f|_(=rBMF2smC|TpqjSApb#MeD)f7Ak2b>k0hEAim*BskL1@Gjiy$WJ;OB3F|C=3vYKsk>B#t)7t@QM_gjfImVIic8;POgZV4s2|iDY&%iF#kv{n%PCQx$)z@DQwB zDQnH9A&>3S;3#dH1t@+t^Dsxvosh1#j#oOk2QY`M6Oqv@!C#|K$FrOao?`jI!Dv1{ zO>DQV(*DW`bJKkAXKP;HZ6m5#r_1o`QVOoc88+vkVUx zBEP&f`buKq7fWDYEof`@e4yclFF%)M%Ro1%Rc0v5H-zS z(r+uP(-03-n-{U`VhLGw(xs@fuN3v%Pt@ z>4PC-Nd4U_?q72aKJ3Xd=jIve*}Pp(U{{*?egJw%_HNVeD5E5IHY#E-Y~DGFTYcXD z$=t{o4KcJ=|1NZKR2&jP#2shOOB;QL4wno(e_>TX?oWu?WoUyZLReikZErA^R8}E zn<`6!!DA(g;CD{wn^Zrj5J@R0`*E;cu51l**||~`G7Eczgdr#5{5NPo`a|*R54);H z?ht=)3SNfnK4(l`J8>U9WIktDE{F%_&!493?~jOmir6=@A#4H^9+LtVL4A`npH3X$uG z(PTa+i-tHj(|wgA_ZxWnXH0OP9X9@_m`O6}gTONw-|vRi)9`|ZYe)IGP;xggwmROP z59A9fg>s+^d%%){!YQ+{}S(OYSTt%De;-cZ2CA| z?X01EJit-31M3`dM}F?UrujH7C;keXOYkvs@$c@Z&$C9XeM_!&jFEB5awDnLbC(ZT zuy9~WRh{D1?<=`XA}n|<-mtc-&C#A=Zzw2zkx(RXF6kKCu%FO^=E4%kKzE!dDMnSO zMP>HiPM>+1lhpfRLFP$`o-e%~F^uA>QILIWjW>;g@JJYeY>$Pc960;c>PJXyaXgZx zb!EJe5G2;xqbUKBF^#0~(T7rT6pu=*FjA%jH!-H=+NFsrSA$h@x6YEk)^10mpVk-> zKa^&BH>z6Oz}=VAA+C4WDeP$~L6uaXMeiAY9r)@^!k!bcxwRwueQ8u_h-1_d)PzVG z53+_qpbmS6{lwkJ;X1b>6#e)Jv?3EUckaW%YUuPPv>N3=S*yr_=o+~F{tQaHbQaV3 z3Ec`h(*9Cd_9Ge!V~9m6Ku4^|5PyD_2Jk?_a&mOT&sSRaXrhtAl_ah1$*SzF*sbgc zz~0E8peg$ax^X~ih?GrGl{N(X^~s5vvrUJ8mY4@c#MJ2UVwM=m!Z7wJbb;KOt?Tvw;hGnb;W^xzW$h1z$(@4)7_tsGztEe%D8S<|4ExNV#AW`Dk~L ziB3ybLQN+WwYJboV_@J7Kv7U2py?hAfH<+%k@RsyMyrI$P_Z_>oZlW!A?>ufjl z_q!LBq`tYCY12rlxC6KjGIBTqYLuk0gHp!10VYac5eG^=P7rC(6DS@_$_ZP_2WuHs z`UM`~D=)Q|)hcWuH|o>un+gYhFL}&oh<=p#4xdEXGv(qzi1wwT6R?;en0Sb93 zqT41S?IQHjW=+^f!YCoZrZx_1Up4bb&EDFek?T!sn}|U}aMGX3HeiwWoh@s)Q9}KF z*}Hoy@he$;`T!{5X#Q`oGCny7WZHogkqV|~Gw}=h<`^JDx^qS#yw4AkxUc5s^qwYn zFd0cb3$CAe?_Z1U5!=?6zb-*=Zb{)NDe}CW z-Rty2&by4DU^>QKT*=^!G6Ohx|DuuS9^gK&jg` zI$B1*>nu{L1!!aY%b6cjgbe?Htx{HI*I@L;j%I&+DR!n5Xib%zJbk%?Ucq5yYZDfp zD`kDhD&p4;&uWC{jM?nFAgGejj+au3@($6^6dMn`hAQVhopUs(3`#KISWfrz+OGE! zLIp?ES|0c{R#~`SRvTbN;c!kV>bJV1^EqTib*ITsmO2ZMrguUuREt7^PL?|`NQL>N zkLR7dUiKMGy9EF2|H6r(#fXYNMn;O3aXxRUZQ$%%dlGj2`v=a}4pQj5Ko}XP$o4uK zX5p~xg+i6|!SnpQe_-So03A8D+P*tvygadO4{v=D2(W-n)~cZtyW~Q9ZTO{>T*&~4mwAmR7Rwn>l(n2)uDPTeKnNIPaN8EA#gM~r3#LgfIv!^;DY*_WvVJi zS%hFC3mA^fbRN;Se`7ac5U0duHZ>KPv<-rSu<7-BXN%gTS^$qr9%vYKcV_fKnfV{d zmTb(>R?mxsgMJ_m;HywlQ^Ny6HVnLX&mTiE$ZWH#|F`vg8LENg0bx!b6?B$oZxkcX ziJU)Awm?u9;&EJ>wh{n9up5DIm@x3a?|;8;m?>XATrxZ8dwy7J_3mEON4GzMP=wVw zGL1cY$an93b-B7>vb8IR0U2jGnmf+n1MO9ZmOTber{<@+&qR@zcG4_+>kbb{hsVc5 z2!3F7sC0>L0I8d-P_fYf7 zn7(cG!*T;Ucy4ZnQ7GW$p{n!r$wSn|`t6j{f5<0FhHCvgw_a>SAiqd{>x!ZVjt;iA zo!V}N-g#b0NeCWmv@ddtF`9@lj}F7Z{R!*Q55ld(DPsMOBlb#TSB#NBagbC{Vxlc5 zC?y5e*!X0!>)h}Cwg8wQ(`aUFw2FkTE}73QlX&2_CMUAo*#IeoWnVrGfrGs{lp52H zr=lnEo1;BpFR$iWC>qc#FLy|NJ*z1klM~tXrSPu{7dTMSi*UkMApD`BE6R5*)X;CZ z3PeDRuXge6{Lsh2iPAR;wF#oY=@t)5j0wY-s9DB{hFCRKum7B!TVQQ}xY$PJR_3Op z46|Fy_n7b0dh%;Fu0DAzCbphilZyuYg#x9};mS(mSx(-dXe6_(_NuDwuD&DfwgQ%wAlDkiuLBJW@3Vi zO@BL7NbigJddBk(eV(n3CH}UmZQ_Rqg@q658a}zXA!85_l(?L2g-Ylf&Y52ixC#`_ ze%~ek*~C4Rov?1i^c}cZpv9M!yXe|R&Vff%?hCeU6u&d4p%{G1#l}rey+;5DEj3G6P#?ed~Ucldy9R$>Sw*1K)fvXx}d;VUmxfjQ_U3GKBY&YzrS&cTTHhK$DKWxSd-P& zHI2IF8@YPrhT4@rt1@iqnV&~-HkJ45UDIi^!RzDj#1}Pjx!qiX@hqe+;58C%{LAUR z`=4BovlNdQ+e&v!K!CX^cMaOW4w08r16Q3FlUXSo-}8UY4*g{@v}U>;5lvp>GZ)lYI*_ zZM-Eaq>(+Lc=>wgjV>MyvewpYIijc`bx~sDStg+?P0t*bk8tkiQ&{g}LPi#IeQ;*J zc)>O~l{7>i=#&$Bwq{eH(U)|%(j+=Nr*k=bkNS9f-(U0_hUqzVaM0(X<%NW7Y^cyR zY5AAEZ3+mSvrHVOI((I5N#;z-tI6r_hAu7n-%|`;_x7RB z?NSd9BJvSvs+<;93rG!L9)Ed6#wti0^P%QfRD{zfm~H*L{*)!uafE$_7dXAKmS(@& z?t1ph{q(YJxozfX+A$E2x6mE`5j9(rek_AvI{!;V?EM}%j+m&`e(DGhrX9|Gsn+u) z)D*_I*e~u*L)*JZlTm<&mkHRz^5&6L)`|;NO_D2`SoxGIWoSTtzzrTIR@VF7-4gK3 zda81nji~14<{_z7(f8wL^HsElO?Ht$7qJiULqQmM(h=6_yk7|1-FeL&D&eWAMQLb? zC`Cl@?CqJ-xjs|iy^5romLzIsA7Sh<*POYM)g_?7k zDWPmsXBmqTA{Td*|Jrp;>%4I%?V`YQwz?8kK!sUQfHl?TDSWcp0HULNJn=6n0jG<6 zreI-J?dG`3|93BajE0tKyDHP^lQpzsag$EQ!8I)nBxY`IeqHSJ2k3X1!>zpD8#aCo z|E_cStOzY(WCU}%%nxpDWgXaCA_q^By57hE=AenlN=ytfAh+fA(YF zJTOt)&w~Rk3oTE-x7CTy;Gq){q|9i#ypKaocsp;VO&h@!(~fCtCeO(?Pp>1R%Qg9Q=r{~m;BwUBfs5Q(IgN^zu^+nn21KDxOC7O2CgX{;^@F6 zMYCZ*fiQPkVuy9vszUB&31aY1`+-mZ8^+Eg@);ShF z1qVv#4t&DGTGy$>OYATA21-kC*rVtjw~zaM9c&+mjI56Abh&)#@Tq*`Kev`u2&r#r z8CSo|VA-AhOq-jAeHFISad3tdbN?| z7gQqdM*6|nQ-ig!GUHvz4+_KCM-IJJ%uOhFj%#M;muo}&D1AWbx#l)LVV(Y{s-n`= z$oAZ=C64`2}?N>GZC39EvV0$#t|0Ay*t zehd$2@4Z;2fBNe`9*=UFKU>HTK!;yAz-dYOy&Fu~$3Y{`Z^lu*;Z+mPj3@G9zK_oN zRNO{dP=whSA6pNGH@rfyMN!njbj&+0atgv3|8C+@z$1AFZ;&x@aDjbrjkgdv1qB%U z=*P-%-t(w*%%(_(Xg%7-2nf^eAv3tXp#`L(0mzSv0rD56Z$)J@aY{$R+w+0Oyuzf81@}0Vb zsj1EI?|KQgY(G=Ws2-QQe?cPu>RXMj1dnEUF+Bi#U}E`GqCUcqok&8nAs*RSQ1Yi< zt0Q0y;yTgsGVwf4d<; z**SI8&v72rBh^2&J%xc4FabsI3Qz8_pTl|iq&q{RPxlkik+z&X zy$&XdL@#o1sTv_r856YnX6DgU#wEj@^hi2Y+?pw=p(6*vMIg+#_h7~C zO~LQ~4zWtk0J-KjwL zR2CzS>>R=t=av`ozf{q)-6=$SCU*@n;BTt3p$d@smalI})$3h`TTg@c#0i7(aTR&8 z-{ooW%*U4nkq(-T*|c@E^C1OD(k9Z2KUNA{LkBs4MAFSc#88+t3nmPRXO7ogW2j*I zDB$jq@Gg68h^)!QQ4+|`6_gPH>(H)B`H=ycEW9oMdgTVm>8$unJvhel;Zx7NVEP z9yxNk3R1Z?lEnJR(7`1X$RdgWg?d9Mr*A80==(-yW^T-4k-q+1LkReXT#F-Kl&pe+ zsziXK*r>{AUPbYf;<>%G19)#HRhj{dijx(yrq66AWCHfvupl!(@)z{VfkAI#Nin5` zKO88@+{wUbjL_#^Kil#zJqi;D%RiQtK5qodop0cRfSj3(1*Y%l&J~a>2xP|vzUQ}s zq*DM}7!~EsuiH;WHXl41qW7Nv`%@Gd8x!^eLNppX_J<`iJ1uVXL}hpPAgFJvTYUlp zECi-~%?@DT7soHpC?6gl0fQlM?hPL1MK(n@f_^N(sxBEX)%A2DTA~D>-e6@lW&?Zp zab=?Oc0hw32zfe9tt*<+oD$YJk#C$(VVrYo=|=^HY*BbRlhJkn0dhu3i3(4t+o7(2I@Y{m8a(A#sy9GR>9JtXTo6>+9W5{}#*@9E$;SDv^KV7zj>)Jn!hlq<&@sV$kHUG< z;WC7oSf*;diO4f&O@rZH!6SKUzoSY9#Q9 za!mUcO-}|WXd~QZt%r6eN`z04gLr0n)F&Wh^J503E~ZpTo3mqD0s*H2U$5PkuEQ{R zJniBMscpLTH=0L13mKvzsP=vsjL;geGalIHNBp!8g-`@GszOL+c$^ZZuPlSJ6yWv_ z^sm18px7(tuhDa*(&SmKu1F|-5)63T`ze`+$8%{NIjP^ld7hFdu1$PvN|p3%jA%1@ zs`B4V`F!Ke2_8Cc27c+x)Ly4$t8Z1*E{v}Vg^~_=GQhHf5_7)CfM1{l1S_-^1u|I=MbX7UUZ+@B zY#NArhvc>}F_0Q=q`uJ_P`;;oW>S990wW>!4G!q8qeYANUdxQDUg%pMD&HRE@Ccx?uY>>aa1n zG(jb0twy?9bDWhh==|s+XnrUXovlxO6j$rlz7Bc7rQe$Ct?2jJ*4pmbxtgp}CO(=qL4O~0qt9JhR*rWDqclS7qxrJ>=ebe~QjsW~~W0@5?$Ep50 z#qjmNFX}J88i*Q5L)L@V7w-2mFqv>1^ZZ~17AY?W0W=elu%cfypzfY)_^B!nep@@+ z{O~WxhhL6&mixXiFff5Y=>+L{9)`w%SK=7m1M9G)qC&lYW|8E4t z-*Q(`0hN`Z0KpaahKhn{1)~6E7W8lD zpl^MeOtzPbri5<$-^zg()`LvGD*ObgHUh7~o ziT=+}M{>Z1IBHvlDqvbVE2ihu_ryAW^d%EdgNqp6NB<;n^;s2kb9*!b zmxSqx2^b-~c)oa0P}{`W&%I?HCm2?bD$V16{zvC7o~~&NOZn_@ddgY((Nv2z!%3_YKL!kU(NqyN_SR?xz*2qyG|JG`+Q`zTkQgnQnwhBV z2pCw?#_iL`zX4j*T0BmZ1Od*^i7E7E-sD82e@x$M4>aYK;hoT&CTHd?#bfwXmp?sT z{B_8nGROS5Au>kB?_vL^v#T(U`oT|3_w;*>ZbD>C_fGea?M$<3)cLzpN<6zrfpxKn zYVCJ@HKOr(Cv@1_hm+)z4+Ev1gh=UfIUW4f`nE3?~NY_L@F=)fl=H`uyo#KM!LVI-^8 z#VwQSX0GN2?8gGRNyIs`S&>aKH8nj9P|$&b6ETmii4E+e@z#Mnz0A&^P-X-l{IJ*) z6krU3BwY&QXcCTczru)8Xi|ukP!fCFw} z5}=eq3ZMZ7Q6{lgdpRb!2~rebngJl}Jw1P*;z)@Lb3ThUs%T67 zC-sCJ9{#Y?O@4CufiBbah(KoJ<7EaOXsml?p1HB>vYW!4Y^CbQ>t(ybtJ|0=}MkSG1pm8G9UkB zDoIu?-fC*!A?Pg#SXW&`7VXr?W`yvTR9%m%#UK_=UQ8`LRaOtS&4_3j++5hp$v4W> zQ+?fSW3}SP@ZyDYtK%Y<=T4i4j{Ckdl)g{5opa4EH{Zf@4lK??oE%&0L<>>+DEJuh z0L|)9d$hG5{5d5xcxZ=l>>9-fzlg`?TH007b+0i3K!uHTsY4a=w%ogw8d{AsDmc#I zJ`u6P_9PxTDXGr2e6~3et;dHAhh@OR+iE;_T)kx``*Su8QO;mA+fLs34{RfjCgR?( zSMD2o6Psw3jt-ifp9M!`%4aw}ad?cEE(SVv_10Cjus$6C=AQ9GVrUzh+zwn^eobLQ zVi|_R!x!oBoLfq;dF|Pz5MR)&`b>A3X(3<$#AbEoT(`zyjXOR6r5r`8Mu%sIn_Rm7 z+_w1_aQJU2(*_BusJ?@{eZ{*EQjOb8!iMK;5<43^iIf_5Szaz;E3A(?KxDEVp*^0-zK<;*`~Jwm$7$D4qkj*liWWRkA43_4K0^vMsw6 zE^xv&m?tJ5Xr4Vhnu_T(wKSxgbk|(==LtdGQGp*RI90`-6%izx=8Mrk!(5T|0osr6 zQ;GsmgF+$Esk-^JF7t)^%eOjZ;H>3*5@bvYlVOrWdPCI4tJ0H`LV(Snq!5tU>Hyy} zaT~Ze^CK;{)LoR4H`qkw14wk`wjVGW%6{Lxp{1ZV z|DGB6J@*Jh1!Y8u*jOnPS!Bs1zG+ZZ291{5ZJe;Vs7pKixDp*bnP? z>vfvdl%uW%+Sss4GYG` zS+0g?KJVbB;Dk2s3ZxTeZe5NH?ZG9S2&!n_9n+w*t3+R(rRi+WBdHupwe$@yn6@k&EXyJs)z=h5sJ1k(&`s z39ZF_`C9QjIRRGWaYA)rp}ag#tsTfi$2*S=0|7@&npfwa@L$`%c^Pip4;_~P<&f#eL281Z-gMYX5V}M%w#D(t-(92)zo_(#nkjaj^J~B)kc5 zTXF-g8XBOMkPb$U!vO}E)>PD#ev4=EG%w)w%H0wT01?fXV8C|NOJ;5miv!;mn%at2 z#KqVKO%&9-9iM=UgS)BGU5HiVDnJtZR}`*e`Ce1td~3f4tsWmShU43%zAfYnRSiYW zYWCM3LcHN`MuDKK&HL^an3D$TiiGa|?hm&t$CNB|C_(M`&YP9N7#FY%ICxTe%4w%t z%n1+)T>6?^E9{;?TZIM6$?3$JWKU1mq4gQxrS5a!Ap(~Zh&VX7K@&UDCaR=>B2eX5f@v@A|3)HJY!~IdaVM%E*0`i~2qH zE^HMxSsl%Z?uL`wN#@Nw{Py+rsM`&t~Ps64~i4#|p5WiQiL z39+K}+5l;m=K%AJ+xz21bW_&$KUu`Bn{BX2qPak8w(wpllrtd$7$MY$T~7l}f7z&W zvC1Ki@GbA-*7)ld#DD+c{%4k=f2W0z9S{PS14yMRtsildjRO`+V2g_ zk}^^df%_=1ECdK6e!fONAePXH=&FGP=|}@oVX_gFbewR4{{#WkBPp*14+M?2`;{Uh zZ~5u{1pPFF6qLMBK%D(3^vD6YY4sh~^lzkohZutCubH3b#*j7?{B{06?HXS_z%ClH zWw_gr6_#{X!~pc8;}~v*8=#r?Lsx@BYsY%=q8KRJvC z(Djem?cu)n(7=GN5P;M6j*XkePx>z^)mgt06@4zDWT1*9{c+=Rt*)S?`VJBOXB?M_ zZ9oW=oJmP9U@q3}@bK`?b?>;=d0!)n_%V>f`CUEm2ADMJ{q2N#V&5K43S8W2aeM9e z+)1Mr6ok>$^+?RgiIa`_21PnH^5s5lKl~ZtYx?h_;UPj%7}80H3KeycK`v3Ex8A z@_iSQBecr@xJ{gs0YbTyEgyRu$LV`>V(*0e4s*?^@K(`Z#VFEfK3}{jEiV7qIug&! zt2WJgm1d~aKWhZ;v^hXj)xT1{>}=O8Z;yZ|r{P5c)J>a-b&HMH0i^rWWp6luAlCo= zOXg&Gir?c_X9qrq-8NB{kT-ECoTt^udiy^d=TNoo)m{RCl-%)G|K=_yw0s6`>n3CF zo&PX(Odxus_g>i-gNM5j6933UhAK*t8kwJ80!7SC?A3J5#xHJ}i{_uGM=_CRYyK!Z z!w0BahNDc)MKfBwx;Lt zl^Fc9zG(;=u>^E?+0+`R=Xh?j*JZF2#!_9O@F?rxoN;$w-bITX}joc8H^&NOG`%yEGY7-GY2m)o1ICeHyZ|JGWnCD}t5+_K8 zKE4l2HB(S!6(2Iu_aYH`CVuFk$GDhk^^gvWV02oWe=f|cbuys_xU{`XEnc3nLLMmH zTQ0yHtOr=(IQ}?WFY?$2vAeYZ#8>-;TQ34B~QpX z8OW0~UF>*bA!>;WQqaDuZLW@|!`lAdWEhj679JmO0ZB`~lc_!w`~Ch z<5Pf;a52$9U!2Ox%NwLXGdPkqU{pIGL%%f;lYD>cI6sQn#hx4KcCbLj%ZtqKBmxT} zAp8sPVJYe5IX`)L)DOKpK{2qftY5KlQldJq%XH6G-TY$E{!PH)PK*J$qrQ1_i!SJ7 zZD5P6{9+x3D1I|=wQ;|5PW?u~-vsjZ4sZUthY3{bK!H{>g(U$7I#60e#X|!J4A$vG z$JUk9suz%S0eG;fEbCEuc?tkm5}5tGxf_*95!OAe*$D%-i74505m;>A0w^f~5oHSA z1-nabU`c@F@-Rt@0Hl{Yd|wGTpYhAeE;t>RH)~#!{H|vseIzOWYpNrQlVDn#(0f8{)6=fu~ogUrz zfFZ{TZZ_vqK%G+;`x_?7$4gzOFpMnmKysjw2Xw+vxHeO0bu}HIb4DNAPfm`>o+Dl@ z7ob@6xo#ihb)ARpaVq@$U1nSH4?b}pN3H*HOh zJWx?}1O&f#M6XP$!-K)J=XJ(pfSd~ZUQe{%cTutPCu9P%Korze4{S`!>MU7ehVqN$o?Xe^v zQDf9$rTP*fhCa&0{ZkvriFL}bY+<08dx_-4V)SB20Tg-w9G0g_bpcYk5#|KmucMic z7Uy28Tz`k%F}3g8)U`h&$t6~bl}c*=-*iHO{aP;(#Cn>0GNp2<^KmR>5BUW(76l3L z@spH_N$M0vSy>o%@pthNuCA|Ofw8k8KrvK~4AquPi*ZJNo%!qEmC_p0*VA)(E;Q`z zgoA>k0Q_hO3#J#n@8D$|Y2OQ5`|~s)VZ6wvQAM3h=TM?r9q>2pu20L3FFG;0{C@b4 z;}R@bZsIwa%<7m59j)H7PX9Kn19?4o2|+6Rs_4s#ja(7M@Kq)mazuBv2hc_R2LLZM zHPVYNsC_uiHGOx(tKtRHCJKB3i1a)C=h?H1FUy^H!F)-Fu0Mxy6 zX$6fNY_*q)n*a|?C%L)oz;4mnP-;%zT=_{n$p3lacvwQ~SYw0C$Rdq1TbN!F=EpRU z2?bE^g91sKTOBLl@ZwKIEdu_H;#NdnAiSiW8V-&>`U4xV6zmAkf`lC76$Uu-et*LVH@b{#{Ur50n%*-T1!Y%L6v+_n zFpR6UE!Wo4kJ(@D4)3Vll!;?1$zFWqoW$@NK=xe{%ml zsbuf=<5X35w1ESgy}<7Tz7a}65QfQnvg=0>u=h69VY9FtINb^$AJ8k@=8Mr0dkEdM z^_NpCTKGhe%he>~vFa25Iw^-m(DXLpyYWy`k%6t}NMHkqYqQfLNs5Yp0i`7!5U^x4 zwZD(IIS_+URAi;AD9pw6Rb5~I>JbBMjsesaLqX*ak1+Gjhp5o?wOt6b`w^n$s~g+5 z)P!Rcs3H(5BeWoPlLv_g*?}Ag!3O;tDi}d}u33wk*MfMsc&_v3rUz;;Kz6BHIF=6UBE%&gs6dkbe4Eqr%o^04QU3)5%E)L*=W#`ahL&iaw2&60GNdrXU=~K0WNejW8Dt$XgJj8) z8OhG@9`7IU{_y^EKIb`~^PK0L>)hA5pYyrSeMUz9_4jwUh=<0ihR-lHTeE0_`}aGZ z*4F;GI8%EV`c^8&T}#Z3)Aw{s@c2&1;4$va-vU2&-@OFcymr|9WNBs`rVIH!!Z=QT zS?Bu2dE?q*AQdG0+g0@R_H6@ickG0T!Lu{1~J?Lu9B2Ax$p~3|nfG-!ElW}$M-xo0fViSZb;Rq#Cej&WRpTn`) zc1^b>wPvzlE4HAW@-W(H@B52is_qDx9@=RMDJj!!ynD}GFJ$1?(}By*N?$rh8P`w& zdmzVRvy0P(Bctor>fT)&y%+}(fo!Wph2^T=H6nEIAD_TqeuvCQBmasge4TReV16wX zGRU2I6Fh}MJCp$(!BDh=1;S%;v6mkFAQ+&=xyKZbuZ zf30qA%!FjE@?xBsp;jK2uN8=v_9W=_Z0H0{Q!u%U*xlquUR!cQEd4QLwXb+Fv7Q@D zEy&8f=kIDu_iHm~s0y~!d-QBHlTUN!;6b5_rqlBCe@>X6)U7bN;DPnPV`D5E$+nYA z2E~0wxj_p(QA_>e)19MxsKeZ$+}u*f07LT8uJuqmH@59B0x2koh+;gIYPC4uk4sG* zlaNs&cl_<%;)Ep@Dpe)PQ0;EqSa4ZflV+3-SkliGWEBUJ98M(hB|;U@WgIgUv$?A& zjUqmP^_4y>rpQ7icBnxz4G7OHkvS-EK2^e;tTwF&H#{CA@M5uUeu}JUO>FFb-EV-EXYEWX4hNcB6 zI^Hp6s=k!6SAJhN@yBZ6wJ3On?6P2J{8(^tnT7Yo)aI@Xbo9QAVKedA|%OG!AX;Nn<#t!++oWK*&RPTL zVOMw69lu*4;fyKD)@J|Yq~#(f^Jmyrroplj7$R-$VUk0^lBAx};EXLBhqG85c{r=A zLcW})mPT~q+PHIxhF(n41L13B1HAcN;L}W%%zpkWEV~0@A}5d@2~tQfM`%0wp=l}) z%A?Fdz$wVxZvxLjW=`U`2uO_O%yvQ`AJMUvAhVJn1dxQ_g=KkPrb4GG(P=&dJ#qJd z*a?!|2_DKDvh!JiRW<-bemaQ0b=TbD(L!z><6w`L4y+>pRMn!-ndk~xf@^DAzOl$n zO#+LveQ;@5x#N`-WGbqctfG7hZevrMVUxDzok#NTW7HIfXH!h2bUDe4ab~a6@?}qZ z1T`$M0x{DU89du2ROeZfiIL-|cx zK0063-h8d5rM;c(WDqcI+Llpy@y{P|LxM2Xnh4l>=w6vutoPw&)CU&sh-5j@JGhZb-kMIwNVd11d+}k=($d> zK>N^(DQGu4I|3b6;OUi%!`D>|)d`31?;_!(q(()+jM(5*8$1Sad`J^*Z!o-5OBM${ zeQ*nmi^F{D4_schNaa7^Sco*OkCaqp*vBsw8I9&zBr!&Ur`trOs*BT8Q$q(f!CUTs z!idWv%0F1f*HR2~T>*8G$hJyqYWYJO%`a)UV92bS1vb(t9woL#uDU^&ot!@mYjWRn5>*SkkJ6<5ab{C5?;n^Y61%{<(x`bFh-W&=^WUNuc`EW0GO&pGfNBeK`{Y; zGQNH)9q0gGugqPD2xfDQLUK7rDg9+b9na-@v-G_Z^3PP5iEH^!ry0v8*vyOpUkq;x%;aDEGmW+q{PvlY(+r-^5&je7xXI_u zSjP&Ew5XI+(c8BgMhkNRuQz{-Sap&29(5u!+fWIe8yNE9W+b8~7hReF1$LY)-`HPlPUW6@iYuXBYfYihTU~ryJ?Qy!Hn7-rf^eoIiL#p?22R)|X!@ zJ|Bv_r3ZI&Q!eNxq@*woNl1*)+Q)B^y}#{{kRarRuJqSP?=RT1cUcA4>)6;*X@7fL zPKh95E^Ba&wXc8*NMObHY`AUSJCX_|B*lO9r)RY>f#)SGJYs#xh<8q12k{Cgz36_Qck5 z6)ftz!78>76ew6RlN2({b=16yhJ7mb=Pzf4qmVcrp;!@ua}C&`GN>zh2Y) zEmKD5lv)T1(fkeDsUUv@TKXO*>Ax)I5;TlXBMOFE02s>uiGH+UlS#?f$P7wV{ z>2>h_IVlH+TSw}&C}aB6LNq#nPkpyzfh@R9sRBpOu3iOQhuoL?U)=hC5%PAWvaKB- XMj%$_ZOn>IuipO;g@5?t diff --git a/doc/tutorial/images/generatorworkings.svg b/doc/tutorial/images/generatorworkings.svg deleted file mode 100644 index 85a7782a..00000000 --- a/doc/tutorial/images/generatorworkings.svg +++ /dev/null @@ -1,392 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - bindingsource code - - - - - - - typesystemdescriptions - - - - customsourcecode - - - - - - libraryheaders - - - - - - Parser - - - - GeneratorBackend - - - - TypeDatabase - - - - - diff --git a/doc/tutorial/introduction.rst b/doc/tutorial/introduction.rst deleted file mode 100644 index 40240f80..00000000 --- a/doc/tutorial/introduction.rst +++ /dev/null @@ -1,32 +0,0 @@ -Binding Generation Tutorial -*************************** - -This tutorial intends to describe the process of binding creation with -Shiboken and using a very simple Qt4 based library will be used as an -example. - -The image below shows the inputs needed to generate the binding source code. - -.. image:: images/generatorworkings.png - -Putting in words, the user provides the headers for the library along with a -`typesystem `_ file -describing how the classes will be exposed in the target language, as well as -any needed custom source code to be merged with the generated source code. - -This tutorial will go through the steps needed to have the binding -ready to be imported and used from a Python program. The tutorial -source code is available as a tar ball `here <../_static/bindingexample.tar.gz>`_. - -**NOTE:** the binding generator is intended to be used with Qt4 based libraries -only, at least for the time being. - -.. toctree:: - :maxdepth: 3 - - libfoo - bindinglibfoo - typesystemcreation - globalheader - buildingthebinding - diff --git a/doc/tutorial/libfoo.rst b/doc/tutorial/libfoo.rst deleted file mode 100644 index bad6b014..00000000 --- a/doc/tutorial/libfoo.rst +++ /dev/null @@ -1,69 +0,0 @@ -.. highlight:: cpp - -.. _gentut-libfoo: - -Creating the foo library -========================= - -In this section it will be presented the code and the build instructions for a -very simple Qt4 based library. It will be used as the subject for this tutorial. - -The Source Code ---------------- - -There is only one class on this foo library plus a ``.pro`` file which means -that the build system used will be `qmake `_ -based. - -Put the files below in a directory called **libfoo**. Be aware that this -directory will be referred by the binding Makefile presented in a next section -of this tutorial. If you want to use other names or paths change the binding -Makefile accordingly. Blind copy'n'paste shortens your life. - -**libfoo/foo.h** -:: - - #ifndef FOO_H - #define FOO_H - - #include - - class Math : public QObject - { - Q_OBJECT - public: - Math() {} - virtual ~Math() {} - int squared(int x); - }; - #endif // FOO_H - - -**libfoo/foo.cpp** -:: - - #include "foo.h" - - int Math::squared(int x) - { - return x * x; - } - - -**libfoo/foo.pro** -:: - - TEMPLATE = lib - TARGET = foo - DEPENDPATH += . - INCLUDEPATH += . - HEADERS += foo.h - SOURCES += foo.cpp - -To build the lib: - -:: - - $ cd libfoo - $ qmake - $ make diff --git a/doc/tutorial/typesystemcreation.rst b/doc/tutorial/typesystemcreation.rst deleted file mode 100644 index 53822233..00000000 --- a/doc/tutorial/typesystemcreation.rst +++ /dev/null @@ -1,136 +0,0 @@ -.. highlight:: xml - -.. _gentut-typesystem: - -Creating the Typesystem Description -=================================== - -The typesystem is an specification used when mapping a C++ based library onto a -corresponding Python module. The specification is a handwritten XML document -listing the types that will be available in the generated binding, modifications -to classes and function signatures to better suit the target language, -and listing the components that should be rejected for the binding. - -**PySide** uses a typesystem format similar to the one used by **QtJambi** and -**QtScript**, thoroughly described in the page *"The Qt Jambi Type System"*. [#]_ - -The divergences between **PySide** and QtScript/QtJambi typesystems will be -highlighted whenever they appear. Things to be aware of when writing -a typesystem will be also mentioned. - -Describing **libfoo** for Python Audiences ------------------------------------------- - -All typesystem files start with the root ``typesystem`` tag. The -``package`` attribute carries the name of the package as it will be seen -from Python. - -Right after that, all the typesystem files providing information required for -the generation process are included in the same fashion as header files in C. - -**foobinding/data/typesystem_foo.xml** -:: - - - - - - - - -The inclusion of other typesystem files is achieved with the -``load-typesystem`` tag. The ``generate`` attribute must be set to ``"no"`` -otherwise the generator will try to create more source code for the already -existing bindings included for reference. - -The C++ classes derived from **QObject** intended to be exposed in the target -language are described with ``object-type`` tags. - - -For this example binding just specifying the name of the class does the trick, -since the generator system will automatically catch the methods with arguments -and return value of known types. These types can be described in the same -typesystem file or in the ones referenced with the ``load-typesystem`` tag. - -In more complex situations method signatures can be changed or rejected with -other tags that can be checked out in the `typesystem `_ -reference. - - -Other Common Cases and Differences ----------------------------------- - -What follows now is some common uses of the typesystem capabilities. All of them -can be seen in the Qt4 typesystem files. They are not used for this binding -tutorial example, so if you just want to have things working ASAP, move along. - -Templates -~~~~~~~~~ - -To ease the process of writing custom code for the binding, recurring pieces of -code can be turned generic with the typesystem template mechanism. -They are declared in a way similar to this snippet: - -:: - - - -And is used as in this example: - -:: - - - - - - -The ``typesystem_template.xml`` file from the Qt4 bindings can be used as a -good resource for examples of this. Check also the QtJambi documentation on -typesystem templates. [#]_ - -Non-QObject Derived Classes -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Even in a Qt4 based library it is common to find classes that doesn't -pertain to the QObject hierarchy, these must be declared as ``value-type``: - -:: - - - - -Unused Tags -~~~~~~~~~~~ - -Some tags defined in the QtScript/QtJambi typesystem has no effect in **PySide** -typesystem, they are: - - + conversion-rule - + argument-map - -Changes to ``"inject-code"`` Tag -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can pass a file name to the **inject-code** tag so the file contents will -be injected in the generated code. - -The ``class`` attribute value ``java`` was changed to ``target``, while -``native`` remained the same. - -Global Functions -~~~~~~~~~~~~~~~~ - -The BoostPythonGenerator supports global functions, you can also reject these functions using -the **rejection** tag like is done to reject classes. Just pass an empty string to -the class attribute. - -:: - - - - -.. [#] http://doc.trolltech.com/qtjambi-4.4/html/com/trolltech/qt/qtjambi-typesystem.html -.. [#] http://doc.trolltech.com/qtjambi-4.4/html/com/trolltech/qt/qtjambi-typesystem.html#using-code-templates From 298b9adfc694feac432f4cc7c747c2f3f2952817 Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Mon, 11 Oct 2010 14:59:49 -0300 Subject: [PATCH 047/564] Qt signals are added to Python wrappers via the PySide::addSignalToWrapper function. --- generator/cppgenerator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index ef8737a2..85058820 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -3054,8 +3054,8 @@ void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaC foreach(QString signature, signatures[funcName]) s << ", \"" + signature << "\""; s << ", NULL);" << endl; - s << INDENT << "PyDict_SetItemString(" + cpythonTypeName(metaClass) + ".super.ht_type.tp_dict"; - s << ", \"" << funcName << "\", signal_item);" << endl; + s << INDENT << "PySide::addSignalToWrapper(&" + cpythonTypeName(metaClass) + ", \""; + s << funcName << "\", signal_item);" << endl; s << INDENT << "Py_DECREF(signal_item);" << endl; } s << endl; From 3ef179b87fb133253181b733e3d1605103632856 Mon Sep 17 00:00:00 2001 From: Lauro Neto Date: Mon, 19 Jul 2010 09:25:30 -0300 Subject: [PATCH 048/564] Adding value-type copy test --- tests/samplebinding/copy_test.py | 48 ++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 tests/samplebinding/copy_test.py diff --git a/tests/samplebinding/copy_test.py b/tests/samplebinding/copy_test.py new file mode 100644 index 00000000..6f761784 --- /dev/null +++ b/tests/samplebinding/copy_test.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# This file is part of the Shiboken Python Bindings Generator project. +# +# Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +# +# Contact: PySide team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# version 2.1 as published by the Free Software Foundation. Please +# review the following information to ensure the GNU Lesser General +# Public License version 2.1 requirements will be met: +# http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +# # +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +'''Test cases for deep copy of objects''' + +import copy +import unittest + +from sample import Point + + +class SimpleCopy(unittest.TestCase): + '''Simple copy of objects''' + + def testCopy(self): + point = Point(0.1, 2.4) + new_point = copy.copy(point) + + self.assert_(point is not new_point) + self.assertEqual(point, new_point) + + +if __name__ == '__main__': + unittest.main() + From 4478a25b66729490e27460a7fa59ae9bceadd1fd Mon Sep 17 00:00:00 2001 From: Lauro Neto Date: Mon, 19 Jul 2010 17:13:51 -0300 Subject: [PATCH 049/564] Initial copy function generator code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Renato Araújo Luciano Wolf --- generator/cppgenerator.cpp | 49 +++++++++++++++++++++++++++++++++++++- generator/cppgenerator.h | 2 ++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index b890df64..1ad7a2d1 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -320,12 +320,18 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl QString className = cpythonTypeName(metaClass).replace(QRegExp("_Type$"), ""); + if (metaClass->typeEntry()->isValue()) + writeCopyFunction(s, metaClass); + // Write single method definitions s << singleMethodDefinitions; // Write methods definition s << "static PyMethodDef " << className << "_methods[] = {" << endl; - s << methodsDefinitions << INDENT << "{0} // Sentinel" << endl; + s << methodsDefinitions << endl; + if (metaClass->typeEntry()->isValue()) + s << INDENT << "{\"__copy__\", (PyCFunction)" << className << "___copy__" << ", METH_NOARGS}," << endl; + s << INDENT << "{0} // Sentinel" << endl; s << "};" << endl << endl; // Write tp_getattro function @@ -2655,6 +2661,47 @@ void CppGenerator::writeTypeAsNumberDefinition(QTextStream& s, const AbstractMet s << "};" << endl << endl; } +void CppGenerator::writeCopyFunction(QTextStream& s, const AbstractMetaClass *metaClass) +{ + QString className = cpythonTypeName(metaClass).replace(QRegExp("_Type$"), ""); + + Indentation indent(INDENT); + + s << "static PyObject *" << className << "___copy__(PyObject *self)" << endl; + s << "{" << endl; + s << INDENT << metaClass->qualifiedCppName() << "* " CPP_SELF_VAR " = 0;" << endl; + s << INDENT << "if (Shiboken::cppObjectIsInvalid(self))" << endl; + { + Indentation indent(INDENT); + s << INDENT << "return 0;" << endl; + } + + s << INDENT << "cppSelf = Shiboken::Converter<" << metaClass->qualifiedCppName() << "*>::toCpp(self);" << endl; + s << INDENT << "PyObject* " PYTHON_RETURN_VAR " = 0;" << endl; + + s << INDENT << metaClass->qualifiedCppName() << "* copy = new " << metaClass->qualifiedCppName(); + s << "(*cppSelf);" << endl; + s << INDENT << PYTHON_RETURN_VAR " = Shiboken::Converter<" << metaClass->qualifiedCppName(); + s << "*>::toPython(copy);" << endl; + + s << INDENT << "SbkBaseWrapper_setOwnership(" PYTHON_RETURN_VAR ", true);" << endl; + + s << endl; + + s << INDENT << "if (PyErr_Occurred() || !" PYTHON_RETURN_VAR ") {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "Py_XDECREF(" PYTHON_RETURN_VAR ");" << endl; + s << INDENT << "return 0;" << endl; + } + + s << INDENT << "}" << endl; + + s << INDENT << "return " PYTHON_RETURN_VAR ";" << endl; + s << "}" << endl; + s << endl; +} + void CppGenerator::writeGetterFunction(QTextStream& s, const AbstractMetaField* metaField) { s << "static PyObject* " << cpythonGetterFunctionName(metaField) << "(PyObject* self, void*)" << endl; diff --git a/generator/cppgenerator.h b/generator/cppgenerator.h index 55591c59..b356ca87 100644 --- a/generator/cppgenerator.h +++ b/generator/cppgenerator.h @@ -137,6 +137,8 @@ class CppGenerator : public ShibokenGenerator void writeTypeAsSequenceDefinition(QTextStream& s, const AbstractMetaClass* metaClass); void writeTypeAsNumberDefinition(QTextStream& s, const AbstractMetaClass* metaClass); + void writeCopyFunction(QTextStream& s, const AbstractMetaClass *metaClass); + void writeGetterFunction(QTextStream& s, const AbstractMetaField* metaField); void writeSetterFunction(QTextStream& s, const AbstractMetaField* metaField); From 6deb06937a34e7ef51098336e0541e543d51b8e0 Mon Sep 17 00:00:00 2001 From: Lauro Neto Date: Tue, 20 Jul 2010 08:52:22 -0300 Subject: [PATCH 050/564] Adding deepcopy test. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Renato Araújo Luciano Wolf --- tests/samplebinding/copy_test.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/samplebinding/copy_test.py b/tests/samplebinding/copy_test.py index 6f761784..3a0ff187 100644 --- a/tests/samplebinding/copy_test.py +++ b/tests/samplebinding/copy_test.py @@ -43,6 +43,18 @@ def testCopy(self): self.assertEqual(point, new_point) +class DeepCopy(unittest.TestCase): + '''Deep copy with shiboken objects''' + + def testDeepCopy(self): + '''Deep copy of value types''' + point = Point(3.1, 4.2) + new_point = copy.deepcopy([point])[0] + + self.assert_(point is not new_point) + self.assertEqual(point, new_point) + + if __name__ == '__main__': unittest.main() From 8d21f82291d2a7bc38da95c938450a68c7e7da12 Mon Sep 17 00:00:00 2001 From: Lauro Neto Date: Tue, 20 Jul 2010 15:32:58 -0300 Subject: [PATCH 051/564] Adding pickling test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Renato Araújo Luciano Wolf --- tests/samplebinding/copy_test.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/samplebinding/copy_test.py b/tests/samplebinding/copy_test.py index 3a0ff187..e347182a 100644 --- a/tests/samplebinding/copy_test.py +++ b/tests/samplebinding/copy_test.py @@ -29,6 +29,12 @@ import copy import unittest +try: + import cPickle as pickle +except ImportError: + import pickle + + from sample import Point @@ -55,6 +61,21 @@ def testDeepCopy(self): self.assertEqual(point, new_point) +class PicklingTest(unittest.TestCase): + '''Support pickling''' + + def testSimple(self): + '''Simple pickling and unpickling''' + + point = Point(10.2, 43.5) + + data = pickle.dumps(point) + new_point = pickle.loads(data) + + self.assertEqual(point, new_point) + self.assert_(point is not new_point) + + if __name__ == '__main__': unittest.main() From d26ecefed858fb548d57f66028f3191b5c298453 Mon Sep 17 00:00:00 2001 From: Lauro Neto Date: Tue, 20 Jul 2010 17:57:08 -0300 Subject: [PATCH 052/564] Inject code for Point.__reduce__ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Renato Araújo Luciano Wolf --- tests/samplebinding/typesystem_sample.xml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 4816b824..84396c06 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -951,6 +951,17 @@ %PYARG_0 = PyString_FromFormat("<Point object at %p: (%d.%d, %d.%d)>", %CPPSELF, x1, x2, y1, y2); + + + + PyObject *type = PyObject_Type(%PYSELF); + PyObject *args = NULL; + + args = Py_BuildValue("(dd)", %CPPSELF.x(), %CPPSELF.y()); + + %PYARG_0 = Py_BuildValue("(OO)", type, args); + + From d0a0db84cf61855c8920d7fe1643c9a568708b8e Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Mon, 11 Oct 2010 15:00:46 -0300 Subject: [PATCH 053/564] Shiboken::showWrapperMap debug function now shows the refcount of held wrappers. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed by Luciano Wolf Reviewed by Renato Araújo --- libshiboken/bindingmanager.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index 5149a4de..93e61b64 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -94,8 +94,12 @@ static void showWrapperMap(const WrapperMap& wrapperMap) printf("-------------------------------\n"); printf("WrapperMap: %p (size: %d)\n", &wrapperMap, (int) wrapperMap.size()); WrapperMap::const_iterator iter; - for (iter = wrapperMap.begin(); iter != wrapperMap.end(); ++iter) - printf("key: %p, value: %p (%s)\n", iter->first, iter->second, iter->second->ob_type->tp_name); + for (iter = wrapperMap.begin(); iter != wrapperMap.end(); ++iter) { + printf("key: %p, value: %p (%s, refcnt: %d)\n", iter->first, + iter->second, + iter->second->ob_type->tp_name, + (int) iter->second->ob_refcnt); + } printf("-------------------------------\n"); } #endif From ca8b2ee1246853f88eafa05a09684369b6150341 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Fri, 15 Oct 2010 13:36:08 -0300 Subject: [PATCH 054/564] Created unit test for unknown class holder. Reviewer: Luciano Wolf Marcelo Lira --- tests/libsample/handle.h | 55 +++++++++++++++++++++++ tests/samplebinding/CMakeLists.txt | 1 + tests/samplebinding/global.h | 1 + tests/samplebinding/handle_conversions.h | 39 ++++++++++++++++ tests/samplebinding/handleholder_test.py | 48 ++++++++++++++++++++ tests/samplebinding/typesystem_sample.xml | 7 +++ 6 files changed, 151 insertions(+) create mode 100644 tests/libsample/handle.h create mode 100644 tests/samplebinding/handle_conversions.h create mode 100644 tests/samplebinding/handleholder_test.py diff --git a/tests/libsample/handle.h b/tests/libsample/handle.h new file mode 100644 index 00000000..f76277f5 --- /dev/null +++ b/tests/libsample/handle.h @@ -0,0 +1,55 @@ +/* + * This file is part of the Shiboken Python Binding Generator project. + * + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef HANDLE_H +#define HANDLE_H + +#include "libsamplemacros.h" + +class OBJ +{ +}; + +typedef OBJ* HANDLE; + +class HandleHolder +{ +public: + explicit HandleHolder(HANDLE ptr = 0) : m_handle(ptr) {} + void set(HANDLE ptr) { m_handle = m_handle; } + HANDLE get() { return m_handle; } + + static HANDLE createHandle() + { + return (HANDLE) new OBJ; + } + + bool compare(HandleHolder* other) + { + return other->m_handle == m_handle; + } +private: + HANDLE m_handle; +}; + +#endif // HANDLE_H + diff --git a/tests/samplebinding/CMakeLists.txt b/tests/samplebinding/CMakeLists.txt index 04be3040..c47ab96a 100644 --- a/tests/samplebinding/CMakeLists.txt +++ b/tests/samplebinding/CMakeLists.txt @@ -21,6 +21,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/derived_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/derived_someinnerclass_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/echo_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/event_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/handleholder_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/implicitconv_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/implicitbase_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/implicittarget_wrapper.cpp diff --git a/tests/samplebinding/global.h b/tests/samplebinding/global.h index 2b8b811e..4677b814 100644 --- a/tests/samplebinding/global.h +++ b/tests/samplebinding/global.h @@ -9,6 +9,7 @@ #include "functions.h" #include "implicitconv.h" #include "overloadsort.h" +#include "handle.h" #include "injectcode.h" #include "list.h" #include "listuser.h" diff --git a/tests/samplebinding/handle_conversions.h b/tests/samplebinding/handle_conversions.h new file mode 100644 index 00000000..2c600807 --- /dev/null +++ b/tests/samplebinding/handle_conversions.h @@ -0,0 +1,39 @@ +#ifndef _HANDLE_CONVERSION_H_ +#define _HANDLE_CONVERSION_H_ + + +namespace Shiboken { +template<> +struct Converter +{ + static inline bool checkType(PyObject* pyObj) + { + return false; + } + + static inline bool isConvertible(PyObject* pyObj) + { + return PyCObject_Check(pyObj); + } + + static inline PyObject* toPython(void* cppobj) + { + assert(true); + return 0; + } + + static inline PyObject* toPython(HANDLE cppobj) + { + return PyCObject_FromVoidPtr(cppobj, 0); + } + + static inline HANDLE toCpp(PyObject* pyobj) + { + + return (HANDLE) PyCObject_AsVoidPtr(pyobj); + } +}; +} + + +#endif diff --git a/tests/samplebinding/handleholder_test.py b/tests/samplebinding/handleholder_test.py new file mode 100644 index 00000000..e1969dff --- /dev/null +++ b/tests/samplebinding/handleholder_test.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# This file is part of the Shiboken Python Bindings Generator project. +# +# Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +# +# Contact: PySide team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# version 2.1 as published by the Free Software Foundation. Please +# review the following information to ensure the GNU Lesser General +# Public License version 2.1 requirements will be met: +# http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +# # +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +'''Test case for a class that holds a unknown handle object.''' + +import unittest + +from sample import HandleHolder + +class HandleHolderTest(unittest.TestCase): + + def testCreation(self): + holder = HandleHolder(HandleHolder.createHandle()) + holder2 = HandleHolder(HandleHolder.createHandle()) + self.assertEquals(holder.compare(holder2), False) + + def testTransfer(self): + holder = HandleHolder() + holder2 = HandleHolder(holder.get()) + self.assert_(holder.compare(holder2)) + + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 84396c06..82684fe8 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -22,6 +22,11 @@ + + + + + @@ -1161,6 +1166,8 @@ + + From d874d137b5062735bbd0fa33b0824d476c0fc127 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 15 Oct 2010 16:04:49 -0300 Subject: [PATCH 055/564] Fix bug#272 - "__del__ never called by python" Reviewer: Marcelo Lira Lauro Moura --- libshiboken/basewrapper.cpp | 41 +++++--------------------- tests/samplebinding/__del___test.py | 45 +++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 33 deletions(-) create mode 100644 tests/samplebinding/__del___test.py diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 189e211c..7f7b8da8 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -246,7 +246,7 @@ static void _destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent) for (; it != pInfo->children.end(); ++it) { SbkBaseWrapper*& child = *it; - // keep this, the wrapper still alive + // keep this, the wrapper still alive if (!SbkBaseWrapper_containsCppWrapper(obj) && SbkBaseWrapper_containsCppWrapper(child) && child->parentInfo) { @@ -316,8 +316,7 @@ void walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visi PyObject* SbkBaseWrapper_TpNew(PyTypeObject* subtype, PyObject*, PyObject*) { - Shiboken::AutoDecRef emptyTuple(PyTuple_New(0)); - SbkBaseWrapper* self = reinterpret_cast(PyBaseObject_Type.tp_new(subtype, emptyTuple, 0)); + SbkBaseWrapper* self = reinterpret_cast(subtype->tp_alloc(subtype, 0)); SbkBaseWrapperType* sbkType = reinterpret_cast(subtype); int numBases = sbkType->is_multicpp ? getNumberOfCppBaseClasses(subtype) : 1; @@ -465,34 +464,8 @@ class DtorCallerVisitor : public HierarchyVisitor SbkBaseWrapper* m_pyObj; }; -static void deallocPythonTypes(PyObject* pyObj) -{ - SbkBaseWrapper* sbkObj = reinterpret_cast(pyObj); - if (sbkObj->weakreflist) - PyObject_ClearWeakRefs(pyObj); - - BindingManager::instance().releaseWrapper(pyObj); - if (SbkBaseWrapper_hasOwnership(sbkObj)) { - DtorCallerVisitor visitor(sbkObj); - walkThroughClassHierarchy(pyObj->ob_type, &visitor); - } - - if (SbkBaseWrapper_hasParentInfo(sbkObj)) - destroyParentInfo(sbkObj); - clearReferences(sbkObj); - - delete[] sbkObj->cptr; - sbkObj->cptr = 0; - - Py_TYPE(pyObj)->tp_free(pyObj); - -} - void deallocWrapper(PyObject* pyObj) { - if (Py_TYPE(pyObj)->tp_del) - Py_TYPE(pyObj)->tp_del(pyObj); - SbkBaseWrapper* sbkObj = reinterpret_cast(pyObj); if (sbkObj->weakreflist) PyObject_ClearWeakRefs(pyObj); @@ -500,8 +473,12 @@ void deallocWrapper(PyObject* pyObj) BindingManager::instance().releaseWrapper(pyObj); if (SbkBaseWrapper_hasOwnership(pyObj)) { SbkBaseWrapperType* sbkType = reinterpret_cast(pyObj->ob_type); - assert(!sbkType->is_multicpp); - sbkType->cpp_dtor(sbkObj->cptr[0]); + if (sbkType->is_multicpp) { + DtorCallerVisitor visitor(sbkObj); + walkThroughClassHierarchy(pyObj->ob_type, &visitor); + } else { + sbkType->cpp_dtor(sbkObj->cptr[0]); + } } if (SbkBaseWrapper_hasParentInfo(pyObj)) @@ -537,7 +514,6 @@ PyObject* SbkBaseWrapperType_TpNew(PyTypeObject* metatype, PyObject* args, PyObj std::list bases = getCppBaseClasses(reinterpret_cast(newType)); if (bases.size() == 1) { SbkBaseWrapperType* parentType = bases.front(); - newType->super.ht_type.tp_dealloc = parentType->super.ht_type.tp_dealloc; newType->mi_offsets = parentType->mi_offsets; newType->mi_init = parentType->mi_init; newType->mi_specialcast = parentType->mi_specialcast; @@ -548,7 +524,6 @@ PyObject* SbkBaseWrapperType_TpNew(PyTypeObject* metatype, PyObject* args, PyObj newType->cpp_dtor = parentType->cpp_dtor; newType->is_multicpp = 0; } else { - newType->super.ht_type.tp_dealloc = &deallocPythonTypes; newType->mi_offsets = 0; newType->mi_init = 0; newType->mi_specialcast = 0; diff --git a/tests/samplebinding/__del___test.py b/tests/samplebinding/__del___test.py new file mode 100644 index 00000000..79263d60 --- /dev/null +++ b/tests/samplebinding/__del___test.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# This file is part of the Shiboken Python Bindings Generator project. +# +# Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +# +# Contact: PySide team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# version 2.1 as published by the Free Software Foundation. Please +# review the following information to ensure the GNU Lesser General +# Public License version 2.1 requirements will be met: +# http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +# # +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +import unittest +import sample + +delCalled = False + +class MyObject(sample.ObjectType): + def __del__(self): + global delCalled + delCalled = True + +class TestDel(unittest.TestCase): + def testIt(self): + a = MyObject() + del a + self.assert_(delCalled) + +if __name__ == '__main__': + unittest.main() + From b548f03130cdd2aa7bdcb4bf00f5da8240fc78ee Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Fri, 15 Oct 2010 17:17:35 -0300 Subject: [PATCH 056/564] Added test for overload decisor handling container dependencies. Explaining with an example. Consider a function called "function" with two signatures accepting a list of Point and a list of PointF, respectively. Consider also that Point is implicitly convertible to PointF. void function(list&) void function(list&) A list of Point should be checked before a list of PointF. Reviewed by Hugo Parente Reviewed by Luciano Wolf --- tests/libsample/CMakeLists.txt | 1 + tests/libsample/listuser.cpp | 12 +++ tests/libsample/listuser.h | 9 ++ tests/libsample/pointf.cpp | 111 ++++++++++++++++++++++ tests/libsample/pointf.h | 78 +++++++++++++++ tests/samplebinding/CMakeLists.txt | 1 + tests/samplebinding/global.h | 1 + tests/samplebinding/list_test.py | 7 +- tests/samplebinding/pointf_test.py | 59 ++++++++++++ tests/samplebinding/typesystem_sample.xml | 36 ++++++- 10 files changed, 312 insertions(+), 3 deletions(-) create mode 100644 tests/libsample/pointf.cpp create mode 100644 tests/libsample/pointf.h create mode 100644 tests/samplebinding/pointf_test.py diff --git a/tests/libsample/CMakeLists.txt b/tests/libsample/CMakeLists.txt index d7bede64..158c0e5e 100644 --- a/tests/libsample/CMakeLists.txt +++ b/tests/libsample/CMakeLists.txt @@ -23,6 +23,7 @@ overload.cpp overloadsort.cpp pairuser.cpp point.cpp +pointf.cpp polygon.cpp protected.cpp reference.cpp diff --git a/tests/libsample/listuser.cpp b/tests/libsample/listuser.cpp index 2110c004..67822d6d 100644 --- a/tests/libsample/listuser.cpp +++ b/tests/libsample/listuser.cpp @@ -62,6 +62,18 @@ ListUser::sumList(std::list vallist) return std::accumulate(vallist.begin(), vallist.end(), 0.0); } +ListUser::ListOfSomething +ListUser::listOfPoints(const std::list& pointlist) +{ + return ListOfPoint; +} + +ListUser::ListOfSomething +ListUser::listOfPoints(const std::list& pointlist) +{ + return ListOfPointF; +} + void ListUser::multiplyPointList(PointList& points, double multiplier) { diff --git a/tests/libsample/listuser.h b/tests/libsample/listuser.h index bbb555be..eb5d4b61 100644 --- a/tests/libsample/listuser.h +++ b/tests/libsample/listuser.h @@ -26,6 +26,7 @@ #include #include "complex.h" #include "point.h" +#include "pointf.h" #include "libsamplemacros.h" @@ -34,6 +35,11 @@ class LIBSAMPLE_API ListUser public: typedef std::list PointList; + enum ListOfSomething { + ListOfPoint, + ListOfPointF + }; + ListUser() {} ListUser(const ListUser& other) : m_lst(other.m_lst) {} virtual ~ListUser() {} @@ -46,6 +52,9 @@ class LIBSAMPLE_API ListUser double sumList(std::list vallist); double sumList(std::list vallist); + static ListOfSomething listOfPoints(const std::list& pointlist); + static ListOfSomething listOfPoints(const std::list& pointlist); + static void multiplyPointList(PointList& points, double multiplier); inline void setList(std::list lst) { m_lst = lst; } diff --git a/tests/libsample/pointf.cpp b/tests/libsample/pointf.cpp new file mode 100644 index 00000000..2464c22b --- /dev/null +++ b/tests/libsample/pointf.cpp @@ -0,0 +1,111 @@ +/* + * This file is part of the Shiboken Python Binding Generator project. + * + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "pointf.h" + +using namespace std; + +PointF::PointF(const Point& point) : m_x(point.x()), m_y(point.y()) +{ +} + +PointF::PointF(double x, double y) : m_x(x), m_y(y) +{ +} + +void +PointF::show() +{ + cout << "(x: " << m_x << ", y: " << m_y << ")"; +} + +bool +PointF::operator==(const PointF& other) +{ + return m_x == other.m_x && m_y == other.m_y; +} + +PointF +PointF::operator+(const PointF& other) +{ + return PointF(m_x + other.m_x, m_y + other.m_y); +} + +PointF +PointF::operator-(const PointF& other) +{ + return PointF(m_x - other.m_x, m_y - other.m_y); +} + +PointF& +PointF::operator+=(PointF &other) +{ + m_x += other.m_x; + m_y += other.m_y; + return *this; +} + +PointF& +PointF::operator-=(PointF &other) +{ + m_x -= other.m_x; + m_y -= other.m_y; + return *this; +} + +PointF +operator*(const PointF& pt, double mult) +{ + return PointF(pt.m_x * mult, pt.m_y * mult); +} + +PointF +operator*(const PointF& pt, int mult) +{ + return PointF(((int) pt.m_x) * mult, ((int) pt.m_y) * mult); +} + +PointF +operator*(double mult, const PointF& pt) +{ + return PointF(pt.m_x * mult, pt.m_y * mult); +} + +PointF +operator*(int mult, const PointF& pt) +{ + return PointF(((int) pt.m_x) * mult, ((int) pt.m_y) * mult); +} + +PointF +operator-(const PointF& pt) +{ + return PointF(-pt.m_x, -pt.m_y); +} + +bool +operator!(const PointF& pt) +{ + return (pt.m_x == 0.0 && pt.m_y == 0.0); +} + diff --git a/tests/libsample/pointf.h b/tests/libsample/pointf.h new file mode 100644 index 00000000..832c3b32 --- /dev/null +++ b/tests/libsample/pointf.h @@ -0,0 +1,78 @@ +/* + * This file is part of the Shiboken Python Binding Generator project. + * + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef POINTF_H +#define POINTF_H + +#include "point.h" +#include + +#include "libsamplemacros.h" + +class LIBSAMPLE_API PointF +{ +public: + PointF(const Point& point); + PointF(double x = 0.0, double y = 0.0); + ~PointF() {} + + inline double x() const { return m_x; } + inline double y() const { return m_y; } + + inline void setX(double x) { m_x = x; } + inline void setY(double y) { m_y = y; } + + // The != operator is not implemented for the purpose of testing + // for the absense of the __ne__ method in the Python binding. + bool operator==(const PointF& other); + + PointF operator+(const PointF& other); + PointF operator-(const PointF& other); + + friend LIBSAMPLE_API PointF operator*(const PointF& pt, double mult); + friend LIBSAMPLE_API PointF operator*(const PointF& pt, int mult); + friend LIBSAMPLE_API PointF operator*(double mult, const PointF& pt); + friend LIBSAMPLE_API PointF operator*(int mult, const PointF& pt); + friend LIBSAMPLE_API PointF operator-(const PointF& pt); + friend LIBSAMPLE_API bool operator!(const PointF& pt); + + PointF& operator+=(PointF &other); + PointF& operator-=(PointF &other); + + void show(); + +private: + double m_x; + double m_y; +}; + +LIBSAMPLE_API PointF operator*(const PointF& pt, double mult); +LIBSAMPLE_API PointF operator*(const PointF& pt, int mult); +LIBSAMPLE_API PointF operator*(double mult, const PointF& pt); +LIBSAMPLE_API PointF operator*(int mult, const PointF& pt); +LIBSAMPLE_API PointF operator-(const PointF& pt); +LIBSAMPLE_API bool operator!(const PointF& pt); + +LIBSAMPLE_API PointF operator*(const PointF& pt, double multiplier); + +#endif // POINTF_H + diff --git a/tests/samplebinding/CMakeLists.txt b/tests/samplebinding/CMakeLists.txt index c47ab96a..3767a3a3 100644 --- a/tests/samplebinding/CMakeLists.txt +++ b/tests/samplebinding/CMakeLists.txt @@ -47,6 +47,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/oddbooluser_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/overload_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/pairuser_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/point_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/pointf_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/pointerholder_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/polygon_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/privatector_wrapper.cpp diff --git a/tests/samplebinding/global.h b/tests/samplebinding/global.h index 4677b814..54a9795f 100644 --- a/tests/samplebinding/global.h +++ b/tests/samplebinding/global.h @@ -26,6 +26,7 @@ #include "overload.h" #include "pairuser.h" #include "point.h" +#include "pointf.h" #include "pointerholder.h" #include "polygon.h" #include "privatector.h" diff --git a/tests/samplebinding/list_test.py b/tests/samplebinding/list_test.py index a71dbe71..0db05943 100644 --- a/tests/samplebinding/list_test.py +++ b/tests/samplebinding/list_test.py @@ -26,10 +26,9 @@ '''Test cases for std::list container conversions''' -import sys import unittest -from sample import ListUser, Point +from sample import ListUser, Point, PointF class ExtendedListUser(ListUser): def __init__(self): @@ -108,6 +107,10 @@ def testConversionOfInvalidLists(self): pts = (Point(1.0, 2.0), 3, Point(5, 6)) self.assertRaises(TypeError, ListUser.multiplyPointList, pts, mult) + def testOverloadMethodReceivingRelatedContainerTypes(self): + self.assertEqual(ListUser.ListOfPointF, ListUser.listOfPoints([PointF()])) + self.assertEqual(ListUser.ListOfPoint, ListUser.listOfPoints([Point()])) + if __name__ == '__main__': unittest.main() diff --git a/tests/samplebinding/pointf_test.py b/tests/samplebinding/pointf_test.py new file mode 100644 index 00000000..f9aac9f2 --- /dev/null +++ b/tests/samplebinding/pointf_test.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# This file is part of the Shiboken Python Bindings Generator project. +# +# Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +# +# Contact: PySide team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# version 2.1 as published by the Free Software Foundation. Please +# review the following information to ensure the GNU Lesser General +# Public License version 2.1 requirements will be met: +# http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +# # +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +'''Test cases for PointF class''' + +import unittest + +from sample import PointF + +class PointFTest(unittest.TestCase): + '''Test case for PointF class, including operator overloads.''' + + def testConstructor(self): + '''Test PointF class constructor.''' + pt = PointF(5.0, 2.3) + self.assertEqual(pt.x(), 5.0) + self.assertEqual(pt.y(), 2.3) + + def testPlusOperator(self): + '''Test PointF class + operator.''' + pt1 = PointF(5.0, 2.3) + pt2 = PointF(0.5, 3.2) + self.assertEqual(pt1 + pt2, PointF(5.0 + 0.5, 2.3 + 3.2)) + + def testEqualOperator(self): + '''Test PointF class == operator.''' + pt1 = PointF(5.0, 2.3) + pt2 = PointF(5.0, 2.3) + pt3 = PointF(0.5, 3.2) + self.assertTrue(pt1 == pt1) + self.assertTrue(pt1 == pt2) + self.assertFalse(pt1 == pt3) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 82684fe8..319cc658 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -969,6 +969,38 @@ + + + + int x1 = (int) %CPPSELF.x(); + int x2 = ((int) (%CPPSELF.x() * 100)) - (x1 * 100); + int y1 = (int) %CPPSELF.y(); + int y2 = ((int) (%CPPSELF.y() * 100)) - (y1 * 100); + %PYARG_0 = PyString_FromFormat("PointF(%d.%d, %d.%d)", x1, x2, y1, y2); + + + + + int x1 = (int) %CPPSELF.x(); + int x2 = ((int) (%CPPSELF.x() * 10)) - (x1 * 10); + int y1 = (int) %CPPSELF.y(); + int y2 = ((int) (%CPPSELF.y() * 10)) - (y1 * 10); + %PYARG_0 = PyString_FromFormat("<PointF object at %p: (%d.%d, %d.%d)>", %CPPSELF, x1, x2, y1, y2); + + + + + + PyObject *type = PyObject_Type(%PYSELF); + PyObject *args = NULL; + + args = Py_BuildValue("(dd)", %CPPSELF.x(), %CPPSELF.y()); + + %PYARG_0 = Py_BuildValue("(OO)", type, args); + + + + @@ -997,7 +1029,9 @@ - + + + From 9078b47fcc5fec2d80a242e8a8f494b5b4c4efd1 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Fri, 15 Oct 2010 19:01:58 -0300 Subject: [PATCH 057/564] Fixed namespace lookup during the class generation. fixes bug #414. Reviewer: Hugo Parente Lima Luciano Wolf --- generator/cppgenerator.cpp | 8 ++++---- libshiboken/basewrapper.cpp | 6 +++++- tests/libsample/samplenamespace.h | 3 +++ tests/samplebinding/typesystem_sample.xml | 4 +++- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 1ad7a2d1..79cabead 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -533,7 +533,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu s << INDENT << THREAD_STATE_SAVER_VAR ".save();" << endl; } - s << INDENT << "return this->" << func->implementingClass()->qualifiedCppName() << "::"; + s << INDENT << "return this->::" << func->implementingClass()->qualifiedCppName() << "::"; writeFunctionCall(s, func, Generator::VirtualCall); } } @@ -2041,7 +2041,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f if (!func->isStatic()) mc << CPP_SELF_VAR "->"; if (!func->isAbstract()) - mc << func->ownerClass()->qualifiedCppName() << "::"; + mc << "::" << func->ownerClass()->qualifiedCppName() << "::"; mc << func->originalName(); #else if (!func->isStatic()) { @@ -2050,7 +2050,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f mc << CPP_SELF_VAR << (func->isProtected() ? ")" : "") << "->"; } if (!func->isAbstract()) - mc << (func->isProtected() ? wrapperName(func->ownerClass()) : func->ownerClass()->qualifiedCppName()) << "::"; + mc << (func->isProtected() ? wrapperName(func->ownerClass()) : "::" + func->ownerClass()->qualifiedCppName()) << "::"; mc << func->originalName() << (func->isProtected() ? "_protected" : ""); #endif } else { @@ -3077,7 +3077,7 @@ void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaC if ((cppSignature != originalSignature) && !knowTypes.contains(originalSignature)) { knowTypes << originalSignature; - s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver<" + s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver<" << cppSignature << " >" << "(\"" << originalSignature << "\");\n"; } diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 7f7b8da8..2c1129b2 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -576,7 +576,11 @@ void setErrorAboutWrongArguments(PyObject* args, const char* funcName, const cha for (int i = 0, max = PyTuple_GET_SIZE(args); i < max; ++i) { if (i) params += ", "; - params += PyTuple_GET_ITEM(args, i)->ob_type->tp_name; + PyObject* arg = PyTuple_GET_ITEM(args, i); + if (PyCObject_Check(arg)) + params += "pointer"; + else + params += arg->ob_type->tp_name; } } else { params = args->ob_type->tp_name; diff --git a/tests/libsample/samplenamespace.h b/tests/libsample/samplenamespace.h index d00bbb1f..da01ac1f 100644 --- a/tests/libsample/samplenamespace.h +++ b/tests/libsample/samplenamespace.h @@ -99,6 +99,9 @@ class SomeClass class DerivedFromNamespace : public SomeClass::SomeInnerClass::OkThisIsRecursiveEnough { public: + //only cause namespace confusion + enum SampleNamespace { + }; virtual OkThisIsRecursiveEnough* someVirtualMethod(OkThisIsRecursiveEnough* arg) { return arg; } inline OkThisIsRecursiveEnough* methodReturningTypeFromParentScope() { return 0; } }; diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 319cc658..9d14681a 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -87,7 +87,9 @@ - + + + From 6b57558fefd3a1e3913e8fe386a07da0d8aeedc3 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Mon, 18 Oct 2010 10:26:53 -0200 Subject: [PATCH 058/564] Fix bug#411 - "Incorrect return statement generated in a function that returns a reference" Reviewer: Luciano Wolf Marcelo Lira --- generator/cppgenerator.cpp | 43 ++++++++++++++++------- tests/libsample/reference.cpp | 3 ++ tests/libsample/reference.h | 11 ++++++ tests/samplebinding/CMakeLists.txt | 1 + tests/samplebinding/global.h | 1 + tests/samplebinding/typesystem_sample.xml | 30 +++++++++++++++- 6 files changed, 75 insertions(+), 14 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 79cabead..e031f39a 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -490,14 +490,36 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu Indentation indentation(INDENT); + QString defaultReturnExpr; + if (func->type()) { + foreach (FunctionModification mod, func->modifications()) { + foreach (ArgumentModification argMod, mod.argument_mods) { + if (argMod.index == 0 && !argMod.replacedDefaultExpression.isEmpty()) { + QRegExp regex("%(\\d+)"); + defaultReturnExpr = argMod.replacedDefaultExpression; + int offset = 0; + while ((offset = regex.indexIn(defaultReturnExpr, offset)) != -1) { + int argId = regex.cap(1).toInt() - 1; + if (argId < 0 || argId > func->arguments().count()) { + ReportHandler::warning("The expression used in return value contains an invalid index."); + break; + } + defaultReturnExpr.replace(regex.cap(0), func->arguments()[argId]->name()); + } + } + } + } + if (defaultReturnExpr.isEmpty()) { + QTextStream s(&defaultReturnExpr); + writeMinimalConstructorCallArguments(s, func->type()); + } + } + if (func->isAbstract() && func->isModifiedRemoved()) { ReportHandler::warning("Pure virtual method \"" + func->ownerClass()->name() + "::" + func->minimalSignature() + "\" must be implement but was completely removed on typesystem."); s << INDENT << "return"; - if (func->type()) { - s << ' '; - writeMinimalConstructorCallArguments(s, func->type()); - } - s << ';' << endl; + + s << ' ' << defaultReturnExpr << ';' << endl; s << '}' << endl << endl; return; } @@ -525,7 +547,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu s << "()' not implemented.\");" << endl; s << INDENT << "return "; if (func->type()) { - writeMinimalConstructorCallArguments(s, func->type()); + s << defaultReturnExpr; } } else { if (func->allowThread()) { @@ -630,10 +652,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu { Indentation indent(INDENT); s << INDENT << "PyErr_Print();" << endl; - s << INDENT << "return "; - if (type) - writeMinimalConstructorCallArguments(s, func->type()); - s << ';' << endl; + s << INDENT << "return " << defaultReturnExpr << ';' << endl; } s << INDENT << '}' << endl; @@ -676,9 +695,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu s << INDENT << "PyErr_Format(PyExc_TypeError, \"Invalid return value in function %s, expected %s, got %s.\", \"" << func->ownerClass()->name() << '.' << func->name() << "\", " << desiredType << ", " PYTHON_RETURN_VAR "->ob_type->tp_name);" << endl; - s << INDENT << "return "; - writeMinimalConstructorCallArguments(s, func->type()); - s << ';' << endl; + s << INDENT << "return " << defaultReturnExpr << ';' << endl; } s << INDENT << "}" << endl; } diff --git a/tests/libsample/reference.cpp b/tests/libsample/reference.cpp index 670395ff..1456b189 100644 --- a/tests/libsample/reference.cpp +++ b/tests/libsample/reference.cpp @@ -67,3 +67,6 @@ Reference::callAlterReferenceIdVirtual(Reference& r) alterReferenceIdVirtual(r); } +ObjTypeReference::~ObjTypeReference() +{ +} diff --git a/tests/libsample/reference.h b/tests/libsample/reference.h index 046a1518..cc9fcc91 100644 --- a/tests/libsample/reference.h +++ b/tests/libsample/reference.h @@ -51,9 +51,20 @@ class LIBSAMPLE_API Reference inline static int multiplier() { return 10; } + virtual Reference& returnMyFirstArg(Reference& ref) { return ref; } + virtual Reference& returnMySecondArg(int a, Reference& ref) { return ref; } private: int m_objId; }; +class LIBSAMPLE_API ObjTypeReference +{ +public: + virtual ~ObjTypeReference(); + virtual ObjTypeReference& returnMyFirstArg(ObjTypeReference& ref) { return ref; } + virtual ObjTypeReference& returnMySecondArg(int a, ObjTypeReference& ref) { return ref; } + virtual ObjTypeReference& justAPureVirtualFunc(ObjTypeReference& ref) = 0; +}; + #endif // REFERENCE_H diff --git a/tests/samplebinding/CMakeLists.txt b/tests/samplebinding/CMakeLists.txt index 3767a3a3..a0f68c54 100644 --- a/tests/samplebinding/CMakeLists.txt +++ b/tests/samplebinding/CMakeLists.txt @@ -43,6 +43,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/nondefaultctor_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/objecttype_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/objecttypelayout_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/objectview_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/objtypereference_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/oddbooluser_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/overload_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/pairuser_wrapper.cpp diff --git a/tests/samplebinding/global.h b/tests/samplebinding/global.h index 54a9795f..8fae4ddf 100644 --- a/tests/samplebinding/global.h +++ b/tests/samplebinding/global.h @@ -21,6 +21,7 @@ #include "nondefaultctor.h" #include "objecttype.h" #include "objecttypelayout.h" +#include "objecttypereference.h" #include "objectview.h" #include "oddbool.h" #include "overload.h" diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 9d14681a..2960ec73 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -623,7 +623,35 @@ --> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From c464a4d10b59396115acbd0340fb15f00d71290b Mon Sep 17 00:00:00 2001 From: renatofilho Date: Mon, 18 Oct 2010 15:28:11 -0300 Subject: [PATCH 059/564] Created test for abstract function with not exported type as agument. Reviewer: Hugo Parente Lima Luciano Wolf --- tests/libother/otherderived.h | 2 ++ tests/libsample/abstract.h | 7 +++++++ tests/libsample/derived.cpp | 1 + tests/libsample/derived.h | 2 ++ tests/samplebinding/typesystem_sample.xml | 4 ++++ 5 files changed, 16 insertions(+) diff --git a/tests/libother/otherderived.h b/tests/libother/otherderived.h index 16f21545..553b14c1 100644 --- a/tests/libother/otherderived.h +++ b/tests/libother/otherderived.h @@ -49,6 +49,8 @@ class LIBOTHER_API OtherDerived : public Abstract // factory method static Abstract* createObject(); + void hideFunction(HideType*) {} ; + protected: inline const char* getClassName() { return className(); } virtual const char* className() { return "OtherDerived"; } diff --git a/tests/libsample/abstract.h b/tests/libsample/abstract.h index bbe39efa..8b68b6ea 100644 --- a/tests/libsample/abstract.h +++ b/tests/libsample/abstract.h @@ -28,6 +28,11 @@ class ObjectType; +// this class is not exported to python +class HideType +{ +}; + class LIBSAMPLE_API Abstract { private: @@ -80,6 +85,8 @@ class LIBSAMPLE_API Abstract void show(PrintFormat format = Verbose); virtual Type type() const { return TpAbstract; } + virtual void hideFunction(HideType* arg) = 0; + protected: virtual const char* className() { return "Abstract"; } diff --git a/tests/libsample/derived.cpp b/tests/libsample/derived.cpp index 98f4395c..408e2425 100644 --- a/tests/libsample/derived.cpp +++ b/tests/libsample/derived.cpp @@ -96,6 +96,7 @@ struct SecretClass : public Abstract { virtual void pureVirtual() {} virtual void* pureVirtualReturningVoidPtr() { return 0; } virtual PrintFormat returnAnEnum() { return Short; } + void hideFunction(HideType*){}; }; Abstract* Derived::triggerImpossibleTypeDiscovery() diff --git a/tests/libsample/derived.h b/tests/libsample/derived.h index 07c11caf..73f132d0 100644 --- a/tests/libsample/derived.h +++ b/tests/libsample/derived.h @@ -76,6 +76,8 @@ class LIBSAMPLE_API Derived : public Abstract static Abstract* triggerImpossibleTypeDiscovery(); static Abstract* triggerAnotherImpossibleTypeDiscovery(); + + void hideFunction(HideType*) {} protected: const char* getClassName() { return className(); } virtual const char* className() { return "Derived"; } diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 2960ec73..0e9b16ca 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -125,6 +125,7 @@ + @@ -1232,6 +1233,9 @@ + + + From 2106919936da6d34a1319ad20e283f8cf8fffbce Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 19 Oct 2010 15:32:31 -0200 Subject: [PATCH 060/564] Write right check type function when guessing the check function for a valid type. --- generator/shibokengenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/shibokengenerator.cpp b/generator/shibokengenerator.cpp index e7d0b7de..a1606e85 100644 --- a/generator/shibokengenerator.cpp +++ b/generator/shibokengenerator.cpp @@ -815,7 +815,7 @@ QString ShibokenGenerator::guessCPythonCheckFunction(const QString& type) { QString retval; AbstractMetaType* metaType = buildAbstractMetaTypeFromString(type); - if (metaType && (metaType->name() != type)) { + if (metaType && !metaType->typeEntry()->isCustom()) { retval = cpythonCheckFunction(metaType); delete metaType; metaType = 0; From dc5e4520f3551c3d0aff0383f4a199541d83c772 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 19 Oct 2010 16:09:42 -0200 Subject: [PATCH 061/564] Fix check of return type by python reimplementations of C++ virtual functions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use isConvertible function instead of checkType when checking the return value of virtual functions returned by python reimplementations when the return value had their type changed by the typesystem. Reviewer: Renato Araújo Luciano Wolf --- generator/cppgenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index e031f39a..7160de04 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -682,7 +682,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu desiredType = "SbkType<" + typeName + " >()->tp_name"; } } else { - s << guessCPythonCheckFunction(func->typeReplaced(0)); + s << guessCPythonIsConvertible(func->typeReplaced(0)); desiredType = '"' + func->typeReplaced(0) + '"'; } s << "(" PYTHON_RETURN_VAR ");" << endl; From 20a12c8037e7c44dfac785f8b710682a4af585ca Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Mon, 18 Oct 2010 16:37:04 -0300 Subject: [PATCH 062/564] Updated the overload sorting to handle convertible types inside containers. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code as it is now will work for containers with wrapped types, and will also consider some primitive types implicitly convertible for dependency sorting purposes. One weakness of the current solution is that it doesn't handle all possible combinations for containers with multiple types. E.g. for Container, with T1 being implicitly convertible from I1, and T2 from I2, dependency resolution will take into account * Container * Container * Container but not * Container For the time being every binding is working fine this way, when the need arises we can fix it, for now let us not slow down the generation. Reviewed by Hugo Parente Reviewed by Renato Araújo --- generator/overloaddata.cpp | 244 +++++++++++++++++++++++++++---------- 1 file changed, 177 insertions(+), 67 deletions(-) diff --git a/generator/overloaddata.cpp b/generator/overloaddata.cpp index a71091ea..9be972f1 100644 --- a/generator/overloaddata.cpp +++ b/generator/overloaddata.cpp @@ -38,6 +38,100 @@ static const TypeEntry* getAliasedTypeEntry(const TypeEntry* typeEntry) return typeEntry; } +static QString getTypeName(const AbstractMetaType* type) +{ + const TypeEntry* typeEntry = getAliasedTypeEntry(type->typeEntry()); + QString typeName = typeEntry->name(); + if (typeEntry->isContainer()) { + QStringList types; + foreach (const AbstractMetaType* cType, type->instantiations()) { + const TypeEntry* typeEntry = getAliasedTypeEntry(cType->typeEntry()); + types << typeEntry->name(); + } + typeName += QString("<%1 >").arg(types.join(",")); + } + return typeName; +} + +static bool typesAreEqual(const AbstractMetaType* typeA, const AbstractMetaType* typeB) +{ + + bool equal = typeA->typeEntry() == typeB->typeEntry(); + if (equal && typeA->isContainer()) { + if (typeA->instantiations().size() != typeB->instantiations().size()) + return false; + for (int i = 0; i < typeA->instantiations().size(); ++i) { + if (!typesAreEqual(typeA->instantiations().at(i), typeB->instantiations().at(i))) + return false; + } + } + return equal; +} + +/** + * OverloadSortData just helps writing clearer code in the + * OverloadData::sortNextOverloads method. + */ +struct OverloadSortData +{ + OverloadSortData() : counter(0) {}; + + /** + * Adds a typeName into the type map without associating it with + * a OverloadData. This is done to express type dependencies that could + * or could not appear in overloaded signatures not processed yet. + */ + void mapType(const QString& typeName) + { + if (map.contains(typeName)) + return; + map[typeName] = counter; + if (!reverseMap.contains(counter)) + reverseMap[counter] = 0; + counter++; + } + + void mapType(OverloadData* overloadData) + { + QString typeName = getTypeName(overloadData->argType()); + map[typeName] = counter; + reverseMap[counter] = overloadData; + counter++; + } + + int lastProcessedItemId() { return counter - 1; } + + int counter; + QHash map; // typeName -> id + QHash reverseMap; // id -> OverloadData; +}; + +/** + * Helper function that returns the name of a container get from containerType argument and + * an instantiation taken either from an implicit conversion expressed by the function argument, + * or from the string argument implicitConvTypeName. + */ +static QString getImplicitConversionTypeName(const AbstractMetaType* containerType, + const AbstractMetaType* instantiation, + const AbstractMetaFunction* function, + const QString& implicitConvTypeName = QString()) +{ + QString impConv; + if (!implicitConvTypeName.isEmpty()) + impConv = implicitConvTypeName; + else if (function->isConversionOperator()) + impConv = function->ownerClass()->typeEntry()->name(); + else + impConv = getTypeName(function->arguments().first()->type()); + + QStringList types; + foreach (const AbstractMetaType* otherType, containerType->instantiations()) + types << (otherType == instantiation ? impConv : getTypeName(otherType)); + + const ContainerTypeEntry* containerTypeEntry = reinterpret_cast(containerType->typeEntry()); + return containerTypeEntry->qualifiedCppName() + '<' + types.join(", ") + " >"; +} + /** * Topologically sort the overloads by implicit convertion order * @@ -50,36 +144,59 @@ static const TypeEntry* getAliasedTypeEntry(const TypeEntry* typeEntry) */ void OverloadData::sortNextOverloads() { - QHash map; // type_name -> id - QHash reverseMap; // id -> type_name + OverloadSortData sortData; bool checkPyObject = false; int pyobjectIndex = 0; + // Primitive types that are not int, long, short, + // char and their respective unsigned counterparts. + QStringList nonIntegerPrimitives; + nonIntegerPrimitives << "float" << "double" << "bool"; + + // Signed integer primitive types. + QStringList signedIntegerPrimitives; + signedIntegerPrimitives << "int" << "short" << "long"; + // sort the children overloads - foreach(OverloadData *ov, m_nextOverloadData) { + foreach(OverloadData *ov, m_nextOverloadData) ov->sortNextOverloads(); - } if (m_nextOverloadData.size() <= 1) return; - // Creates the map and reverseMap, to map type names to ids, these ids will be used by the topological - // sort algorithm, because is easier and faster to work with graph sorting using integers. - int i = 0; + // Populates the OverloadSortData object containing map and reverseMap, to map type names to ids, + // these ids will be used by the topological sort algorithm, because is easier and faster to work + // with graph sorting using integers. foreach(OverloadData* ov, m_nextOverloadData) { - const TypeEntry* typeEntry = getAliasedTypeEntry(ov->argType()->typeEntry()); - map[typeEntry->name()] = i; - reverseMap[i] = ov; - - if (!checkPyObject && typeEntry->name().contains("PyObject")) { + sortData.mapType(ov); + if (!checkPyObject && getTypeName(ov->argType()).contains("PyObject")) { checkPyObject = true; - pyobjectIndex = i; + pyobjectIndex = sortData.lastProcessedItemId(); + } + + foreach (const AbstractMetaType* instantiation, ov->argType()->instantiations()) { + // Add dependencies for type instantiation of container. + QString typeName = getTypeName(instantiation); + sortData.mapType(typeName); + + // Build dependency for implicit conversion types instantiations for base container. + // For example, considering signatures "method(list)" and "method(list)", + // and being PointF implicitly convertible from Point, an list instantiation with T + // as Point must come before the PointF instantiation, or else list will never + // be called. In the case of primitive types, list must come before list. + if (instantiation->isPrimitive() && (signedIntegerPrimitives.contains(instantiation->name()))) { + foreach (const QString& primitive, nonIntegerPrimitives) + sortData.mapType(getImplicitConversionTypeName(ov->argType(), instantiation, 0, primitive)); + } else { + foreach (const AbstractMetaFunction* function, m_generator->implicitConversions(instantiation)) + sortData.mapType(getImplicitConversionTypeName(ov->argType(), instantiation, function)); + } } - i++; } + // Create the graph of type dependencies based on implicit conversions. - Graph graph(reverseMap.count()); + Graph graph(sortData.reverseMap.count()); // All C++ primitive types, add any forgotten type AT THE END OF THIS LIST! const char* primitiveTypes[] = {"int", "unsigned int", @@ -96,28 +213,25 @@ void OverloadData::sortNextOverloads() const int numPrimitives = sizeof(primitiveTypes)/sizeof(const char*); bool hasPrimitive[numPrimitives]; for (int i = 0; i < numPrimitives; ++i) - hasPrimitive[i] = map.contains(primitiveTypes[i]); - // just some alias - bool haveInt = hasPrimitive[0]; - bool haveLong = hasPrimitive[2]; - bool haveShort = hasPrimitive[4]; + hasPrimitive[i] = sortData.map.contains(primitiveTypes[i]); foreach(OverloadData* ov, m_nextOverloadData) { const AbstractMetaType* targetType = ov->argType(); const TypeEntry* targetTypeEntry = getAliasedTypeEntry(targetType->typeEntry()); + QString targetTypeEntryName = getTypeName(targetType); - foreach(AbstractMetaFunction* function, m_generator->implicitConversions(ov->argType())) { + foreach(AbstractMetaFunction* function, m_generator->implicitConversions(targetType)) { QString convertibleType; if (function->isConversionOperator()) convertibleType = function->ownerClass()->typeEntry()->name(); else - convertibleType = function->arguments().first()->type()->typeEntry()->name(); + convertibleType = getTypeName(function->arguments().first()->type()); - if (!map.contains(convertibleType)) + if (!sortData.map.contains(convertibleType)) continue; - int targetTypeId = map[targetTypeEntry->name()]; - int convertibleTypeId = map[convertibleType]; + int targetTypeId = sortData.map[targetTypeEntryName]; + int convertibleTypeId = sortData.map[convertibleType]; // If a reverse pair already exists, remove it. Probably due to the // container check (This happened to QVariant and QHash) @@ -125,61 +239,54 @@ void OverloadData::sortNextOverloads() graph.addEdge(convertibleTypeId, targetTypeId); } - if (targetType->hasInstantiations()) { - foreach(const AbstractMetaType *instantiation, targetType->instantiations()) { - if (map.contains(instantiation->typeEntry()->name())) { - int target = map[targetTypeEntry->name()]; - int convertible = map[instantiation->typeEntry()->name()]; - - if (!graph.containsEdge(target, convertible)) // Avoid cyclic dependency. - graph.addEdge(convertible, target); + foreach (const AbstractMetaType* instantiation, targetType->instantiations()) { + if (sortData.map.contains(getTypeName(instantiation))) { + int target = sortData.map[targetTypeEntryName]; + int convertible = sortData.map[getTypeName(instantiation)]; + + if (!graph.containsEdge(target, convertible)) // Avoid cyclic dependency. + graph.addEdge(convertible, target); + + if (instantiation->isPrimitive() && (signedIntegerPrimitives.contains(instantiation->name()))) { + foreach (const QString& primitive, nonIntegerPrimitives) { + QString convertibleTypeName = getImplicitConversionTypeName(ov->argType(), instantiation, 0, primitive); + if (!graph.containsEdge(target, sortData.map[convertibleTypeName])) // Avoid cyclic dependency. + graph.addEdge(sortData.map[convertibleTypeName], target); + } + + } else { + foreach (const AbstractMetaFunction* function, m_generator->implicitConversions(instantiation)) { + QString convertibleTypeName = getImplicitConversionTypeName(ov->argType(), instantiation, function); + if (!graph.containsEdge(target, sortData.map[convertibleTypeName])) // Avoid cyclic dependency. + graph.addEdge(sortData.map[convertibleTypeName], target); + } } } } /* Add dependency on PyObject, so its check is the last one (too generic) */ - if (checkPyObject && !targetTypeEntry->name().contains("PyObject")) { - graph.addEdge(map[targetTypeEntry->name()], pyobjectIndex); - } + if (checkPyObject && !targetTypeEntryName.contains("PyObject")) + graph.addEdge(sortData.map[targetTypeEntryName], pyobjectIndex); if (targetTypeEntry->isEnum()) { for (int i = 0; i < numPrimitives; ++i) { if (hasPrimitive[i]) - graph.addEdge(map[targetTypeEntry->name()], map[primitiveTypes[i]]); + graph.addEdge(sortData.map[targetTypeEntryName], sortData.map[primitiveTypes[i]]); } } } // Special case for double(int i) (not tracked by m_generator->implicitConversions - if (haveInt) { - if (map.contains("float")) - graph.addEdge(map["float"], map["int"]); - if (map.contains("double")) - graph.addEdge(map["double"], map["int"]); - if (map.contains("bool")) - graph.addEdge(map["bool"], map["int"]); - } - - if (haveShort) { - if (map.contains("float")) - graph.addEdge(map["float"], map["short"]); - if (map.contains("double")) - graph.addEdge(map["double"], map["short"]); - if (map.contains("bool")) - graph.addEdge(map["bool"], map["short"]); - } - - if (haveLong) { - if (map.contains("float")) - graph.addEdge(map["float"], map["long"]); - if (map.contains("double")) - graph.addEdge(map["double"], map["long"]); - if (map.contains("bool")) - graph.addEdge(map["bool"], map["long"]); + foreach (const QString& signedIntegerName, signedIntegerPrimitives) { + if (sortData.map.contains(signedIntegerName)) { + foreach (const QString& nonIntegerName, nonIntegerPrimitives) { + if (sortData.map.contains(nonIntegerName)) + graph.addEdge(sortData.map[nonIntegerName], sortData.map[signedIntegerName]); + } + } } - // sort the overloads topologicaly based on the deps graph. - + // sort the overloads topologically based on the dependency graph. QLinkedList unmappedResult = graph.topologicalSort(); if (unmappedResult.isEmpty()) { QString funcName = referenceFunction()->name(); @@ -189,8 +296,11 @@ void OverloadData::sortNextOverloads() } m_nextOverloadData.clear(); - foreach(int i, unmappedResult) - m_nextOverloadData << reverseMap[i]; + foreach(int i, unmappedResult) { + if (!sortData.reverseMap[i]) + continue; + m_nextOverloadData << sortData.reverseMap[i]; + } } /** @@ -285,7 +395,7 @@ OverloadData* OverloadData::addOverloadData(const AbstractMetaFunction* func, // for it, unless the next argument also have a identical type replacement. QString replacedArg = func->typeReplaced(tmp->m_argPos + 1); bool argsReplaced = !replacedArg.isEmpty() || !tmp->m_argTypeReplaced.isEmpty(); - if ((!argsReplaced && tmp->m_argType->typeEntry() == argType->typeEntry()) + if ((!argsReplaced && typesAreEqual(tmp->m_argType, argType)) || (argsReplaced && replacedArg == tmp->argumentTypeReplaced())) { tmp->addOverload(func); overloadData = tmp; From 4ecf999ebfd00a604de6a8e0859a65f2489263aa Mon Sep 17 00:00:00 2001 From: renatofilho Date: Wed, 20 Oct 2010 11:44:09 -0300 Subject: [PATCH 063/564] Fixed signal register function. Fixes bug #422. Reviewer: Luciano Wolf Marcelo Lira --- generator/cppgenerator.cpp | 12 +++--------- tests/libother/otherderived.h | 2 +- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 48b5e6ca..d3300423 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -3083,20 +3083,14 @@ void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaC signature += ", "; AbstractMetaArgument *a = cppSignal->arguments().at(i); AbstractMetaType* type = a->type(); - QString cppSignature = translateType(type, metaClass, Generator::ExcludeConst | Generator::ExcludeReference).trimmed(); - QString originalSignature = translateType(type, metaClass, Generator::OriginalName | Generator::ExcludeConst | Generator::ExcludeReference).trimmed(); - if (cppSignature.contains("*")) - cppSignature = cppSignature.replace("*", "").trimmed(); - - if (originalSignature.contains("*")) - originalSignature = originalSignature.replace("*", "").trimmed(); - + QString cppSignature = QMetaObject::normalizedType(qPrintable(type->cppSignature())); + QString originalSignature = QMetaObject::normalizedType(qPrintable(type->originalTypeDescription())); if ((cppSignature != originalSignature) && !knowTypes.contains(originalSignature)) { knowTypes << originalSignature; s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver<" << cppSignature << " >" - << "(\"" << originalSignature << "\");\n"; + << "(\"" << originalSignature << "\"); // " << type->cppSignature() << "\n"; } signature += type->originalTypeDescription(); } diff --git a/tests/libother/otherderived.h b/tests/libother/otherderived.h index 553b14c1..8685f8c0 100644 --- a/tests/libother/otherderived.h +++ b/tests/libother/otherderived.h @@ -49,7 +49,7 @@ class LIBOTHER_API OtherDerived : public Abstract // factory method static Abstract* createObject(); - void hideFunction(HideType*) {} ; + void hideFunction(HideType*) {} protected: inline const char* getClassName() { return className(); } From dfa7a3c2caae1e4c162423d9f2bb5d6f63977bcf Mon Sep 17 00:00:00 2001 From: renatofilho Date: Thu, 21 Oct 2010 13:22:25 -0300 Subject: [PATCH 064/564] Updated code generation to new libpyside API. Reviewer: Luciano Wolf Marcelo Lira --- generator/cppgenerator.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index d3300423..01db203e 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2014,7 +2014,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f if (func->injectedCodeSnips(CodeSnip::Any, TypeSystem::TargetLangCode).isEmpty()) { qFatal(qPrintable("No way to call \"" + func->ownerClass()->name() + "::" + func->minimalSignature() - + "\" with the modifications described in the type system file")); + + "\" with the modifications described in the type system file"), NULL); } } else if (func->isOperatorOverload()) { QString firstArg("(*" CPP_SELF_VAR ")"); @@ -3535,10 +3535,10 @@ void CppGenerator::writeSetattroFunction(QTextStream& s, const AbstractMetaClass s << "static int " << cpythonSetattroFunctionName(metaClass) << "(PyObject* self, PyObject* name, PyObject* value)" << endl; s << '{' << endl; if (usePySideExtensions()) { - s << INDENT << "Shiboken::AutoDecRef pp(PySide::qpropertyGetObject(self, name));" << endl; + s << INDENT << "Shiboken::AutoDecRef pp(reinterpret_cast(PySide::qpropertyGetObject(self, name)));" << endl; s << INDENT << "if (!pp.isNull())" << endl; Indentation indent(INDENT); - s << INDENT << INDENT << "return PySide::qpropertySet(pp, self, value);" << endl; + s << INDENT << "return PySide::qpropertySet(reinterpret_cast(pp.object()), self, value);" << endl; } s << INDENT << "return PyObject_GenericSetAttr(self, name, value);" << endl; s << '}' << endl; @@ -3579,7 +3579,7 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, const AbstractMetaClass s << INDENT << "if (attr && PySide::isQPropertyType(attr)) {" << endl; { Indentation indent(INDENT); - s << INDENT << "PyObject *value = PySide::qpropertyGet(attr, self);" << endl; + s << INDENT << "PyObject *value = PySide::qpropertyGet(reinterpret_cast(attr), self);" << endl; s << INDENT << "if (!value)" << endl; { Indentation indentation(INDENT); From 3b4856db47d3786f9aeb1cb2c9174e47c7b5f51d Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 20 Oct 2010 18:56:28 -0200 Subject: [PATCH 065/564] Fix reference leak when registering enum types. --- generator/cppgenerator.cpp | 28 +++++++--------------------- libshiboken/pyenum.cpp | 2 +- 2 files changed, 8 insertions(+), 22 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 01db203e..051af21c 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2981,8 +2981,6 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << cpythonName << "_Type) < 0)" << endl; s << INDENT << INDENT << "return;" << endl; - s << INDENT << "Py_INCREF(&" << cpythonName << "_Type);" << endl; - s << INDENT << addFunction << endl; s << INDENT << INDENT << INDENT << '\"' << cppEnum->name() << "\","; s << "((PyObject*)&" << cpythonName << "_Type));" << endl << endl; @@ -2996,8 +2994,6 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << flagsName << "_Type) < 0)" << endl; s << INDENT << INDENT << "return;" << endl; - s << INDENT << "Py_INCREF(&" << flagsName << "_Type);" << endl; - s << INDENT << addFunction << endl; s << INDENT << INDENT << INDENT << '\"' << flags->flagsName() << "\","; s << "((PyObject*)&" << flagsName << "_Type));" << endl << endl; @@ -3027,11 +3023,8 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu QString enumItemText = "enum_item"; if (!cppEnum->isAnonymous()) { s << INDENT << "enum_item = Shiboken::SbkEnumObject_New(&"; - s << cpythonName << "_Type," << endl; - { - Indentation indent(INDENT); - s << INDENT << enumValueText << ", \"" << enumValue->name() << "\");" << endl; - } + s << cpythonName << "_Type," << enumValueText << ", \""; + s << enumValue->name() << "\");" << endl; } else if (cppEnum->enclosingClass()) { s << INDENT << "enum_item = PyInt_FromLong(" << enumValueText << ");" << endl; shouldDecrefNumber = true; @@ -3039,22 +3032,16 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu enumItemText = enumValueText; } - s << INDENT << addFunction << endl; - { - Indentation indent(INDENT); - s << INDENT << '"' << enumValue->name() << "\", " << enumItemText << ");" << endl; - } + s << INDENT << addFunction << '"' << enumValue->name() << "\", " << enumItemText << ");" << endl; if (shouldDecrefNumber) s << INDENT << "Py_DECREF(enum_item);" << endl; if (!cppEnum->isAnonymous()) { - s << INDENT << "PyDict_SetItemString(" << cpythonName << "_Type.tp_dict," << endl; - { - Indentation indent(INDENT); - s << INDENT << '"' << enumValue->name() << "\", enum_item);" << endl; - } + s << INDENT << "Py_DECREF(enum_item);" << endl; + s << INDENT << "PyDict_SetItemString(" << cpythonName << "_Type.tp_dict,"; + s << '"' << enumValue->name() << "\", enum_item);" << endl; + s << INDENT << "Py_DECREF(enum_item);" << endl; } - } if (!cppEnum->isAnonymous()) { @@ -3424,7 +3411,6 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m s << INDENT << "PyDict_SetItemString(module," << "\"" << metaClass->name() << "\", (PyObject*)&" << pyTypeName << ");" << endl; } else { - s << INDENT << "Py_INCREF(reinterpret_cast(&" << pyTypeName << "));" << endl; s << INDENT << "PyModule_AddObject(module, \"" << metaClass->name() << "\"," << endl; Indentation indent(INDENT); s << INDENT << "((PyObject*)&" << pyTypeName << "));" << endl << endl; diff --git a/libshiboken/pyenum.cpp b/libshiboken/pyenum.cpp index 315f7c61..baa56087 100644 --- a/libshiboken/pyenum.cpp +++ b/libshiboken/pyenum.cpp @@ -84,7 +84,7 @@ SbkEnumObject_New(PyTypeObject *type, long item_value, PyObject* item_name) { if (!item_name) item_name = PyString_FromString(""); - SbkEnumObject* enum_obj = (SbkEnumObject*) type->tp_alloc(type, 0); + SbkEnumObject* enum_obj = PyObject_New(SbkEnumObject, type); enum_obj->ob_name = item_name; enum_obj->ob_ival = item_value; return (PyObject*) enum_obj; From ca7b986f9b97f3fec3b44224d2e4117ff203fad6 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 21 Oct 2010 13:57:34 -0200 Subject: [PATCH 066/564] Remove pydict ref leak on pyenum.cpp. --- libshiboken/pyenum.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libshiboken/pyenum.cpp b/libshiboken/pyenum.cpp index baa56087..6295c915 100644 --- a/libshiboken/pyenum.cpp +++ b/libshiboken/pyenum.cpp @@ -108,6 +108,7 @@ SbkEnumObject_New(PyTypeObject *type, long item_value, const char* item_name) if (!values) { values = PyDict_New(); PyDict_SetItemString(type->tp_dict, const_cast("values"), values); + Py_DECREF(values); // ^ values still alive, because setitemstring incref it } PyDict_SetItemString(values, item_name, enum_obj); } From 05cab011045b73150d3c82d28bc8a30f2ec4f1ed Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 21 Oct 2010 18:12:18 -0200 Subject: [PATCH 067/564] Removes Converter, because the missuse of it causes memory leak . --- libshiboken/conversions.h | 9 --------- 1 file changed, 9 deletions(-) diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index 376b1aca..1dbc1840 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -520,15 +520,6 @@ struct Converter_CString }; template <> struct Converter : Converter_CString {}; -template <> struct Converter : Converter_CString -{ - static inline char* toCpp(PyObject* pyobj) - { - if (pyobj == Py_None) - return 0; - return strdup(PyString_AsString(pyobj)); - } -}; template <> struct Converter : Converter_CString { From 7b2a6342fbb27dce8977cb0c5f385b7798186b02 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 21 Oct 2010 18:13:21 -0200 Subject: [PATCH 068/564] Fix memory leak when someone tries to register a type already registered. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Luciano Wolf Renato Araújo --- libshiboken/typeresolver.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libshiboken/typeresolver.cpp b/libshiboken/typeresolver.cpp index d1439ef8..89bc6329 100644 --- a/libshiboken/typeresolver.cpp +++ b/libshiboken/typeresolver.cpp @@ -57,7 +57,11 @@ void Shiboken::initTypeResolver() static void registerTypeResolver(TypeResolver* resolver) { - typeResolverMap[resolver->typeName()] = resolver; + TypeResolver*& v = typeResolverMap[resolver->typeName()]; + if (!v) + v = resolver; + else + delete resolver; // Discard type resolvers already registered } TypeResolver::TypeResolver(const char* typeName, TypeResolver::CppToPythonFunc cppToPy, TypeResolver::PythonToCppFunc pyToCpp, PyTypeObject* pyType, TypeResolver::DeleteObjectFunc deleter) From ee21e7e6688933d403886d272fe35efd453a8dd0 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Fri, 22 Oct 2010 14:44:11 -0300 Subject: [PATCH 069/564] Fixed Wrapper object parent invalidation process. Fixes bug #432. Reviewer: Hugo Parente Lima Luciano Wolf --- libshiboken/basewrapper.cpp | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 2c1129b2..4983f678 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -242,24 +242,26 @@ static void _destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent) if (removeFromParent && pInfo && pInfo->parent) removeParent(obj); - ChildrenList::iterator it = pInfo->children.begin(); - for (; it != pInfo->children.end(); ++it) { - SbkBaseWrapper*& child = *it; - - // keep this, the wrapper still alive - if (!SbkBaseWrapper_containsCppWrapper(obj) && - SbkBaseWrapper_containsCppWrapper(child) && - child->parentInfo) { - child->parentInfo->parent = 0; - child->parentInfo->hasWrapperRef = true; - SbkBaseWrapper_setOwnership(child, false); - } else { - _destroyParentInfo(child, false); - Py_DECREF(child); + if (pInfo) { + ChildrenList::iterator it = pInfo->children.begin(); + for (; it != pInfo->children.end(); ++it) { + SbkBaseWrapper*& child = *it; + + // keep this, the wrapper still alive + if (!SbkBaseWrapper_containsCppWrapper(obj) && + SbkBaseWrapper_containsCppWrapper(child) && + child->parentInfo) { + child->parentInfo->parent = 0; + child->parentInfo->hasWrapperRef = true; + SbkBaseWrapper_setOwnership(child, false); + } else { + _destroyParentInfo(child, false); + Py_DECREF(child); + } } + delete pInfo; + obj->parentInfo = 0; } - delete pInfo; - obj->parentInfo = 0; } void destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent) From 21cdd2a9adcfb80c0aa5daace04c38b8d8040311 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Fri, 22 Oct 2010 18:39:49 -0300 Subject: [PATCH 070/564] Ignore namespace crash on windows. Reviewer: Hugo Parente Lima --- tests/libsample/samplenamespace.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/libsample/samplenamespace.h b/tests/libsample/samplenamespace.h index da01ac1f..7ac1ec19 100644 --- a/tests/libsample/samplenamespace.h +++ b/tests/libsample/samplenamespace.h @@ -99,9 +99,11 @@ class SomeClass class DerivedFromNamespace : public SomeClass::SomeInnerClass::OkThisIsRecursiveEnough { public: +#ifndef _MSC_VER //only cause namespace confusion enum SampleNamespace { }; +#endif virtual OkThisIsRecursiveEnough* someVirtualMethod(OkThisIsRecursiveEnough* arg) { return arg; } inline OkThisIsRecursiveEnough* methodReturningTypeFromParentScope() { return 0; } }; From 7368a0a533c12ba09e7713695415e1f247763883 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 22 Oct 2010 19:07:01 -0200 Subject: [PATCH 071/564] Added BindingManager::getAllPyObjects method. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This functions returns all PyObjects under the umbrella of BindingManager. Reviewer: Luciano Wolf Renato Araújo --- libshiboken/bindingmanager.cpp | 20 ++++++++++++++------ libshiboken/bindingmanager.h | 2 ++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index 93e61b64..38dc4eb8 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -144,15 +144,12 @@ BindingManager::~BindingManager() #ifndef NDEBUG showWrapperMap(m_d->wrapperMapper); #endif - assert(m_d->wrapperMapper.size() == 0); - /* Cleanup hanging references. We just invalidate them as when * the BindingManager is being destroyed the interpreter is alredy * shutting down. */ - WrapperMap::iterator iter = m_d->wrapperMapper.begin(); - for (;iter != m_d->wrapperMapper.end(); ++iter) - invalidateWrapper(iter->second); - + while (!m_d->wrapperMapper.empty()) + invalidateWrapper(m_d->wrapperMapper.begin()->second); + assert(m_d->wrapperMapper.size() == 0); delete m_d; } @@ -346,5 +343,16 @@ SbkBaseWrapperType* BindingManager::resolveType(void* cptr, Shiboken::SbkBaseWra return identifiedType ? identifiedType : type; } +std::set< PyObject* > BindingManager::getAllPyObjects() +{ + std::set pyObjects; + const WrapperMap& wrappersMap = m_d->wrapperMapper; + WrapperMap::const_iterator it = wrappersMap.begin(); + for (; it != wrappersMap.end(); ++it) + pyObjects.insert(it->second); + + return pyObjects; +} + } // namespace Shiboken diff --git a/libshiboken/bindingmanager.h b/libshiboken/bindingmanager.h index cec4a78f..d7cec27b 100644 --- a/libshiboken/bindingmanager.h +++ b/libshiboken/bindingmanager.h @@ -24,6 +24,7 @@ #define BINDINGMANAGER_H #include +#include #include "shibokenmacros.h" namespace Shiboken @@ -61,6 +62,7 @@ class LIBSHIBOKEN_API BindingManager /// Called by wrapper destructor void destroyWrapper(const void* cptr); void destroyWrapper(SbkBaseWrapper* wrapper); + std::set getAllPyObjects(); private: ~BindingManager(); // disable copy From 1f7d295c511062f8973a3e9554173752549b0bc6 Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Mon, 25 Oct 2010 16:30:40 -0300 Subject: [PATCH 072/564] Updated Shiboken cmake files to provide build type information. The build type information, contained in the the SHIBOKEN_BUILD_TYPE variable, will tell modules linking with libshiboken if it was built in Release or Debug mode. The SHIBOKEN_PYTHON_INTERPRETER variable was also added to the cmake Shiboken files, to make it known which Python interpreter (normal or debug, in systems where this separation exists). SHIBOKEN_PYTHON_LIBRARIES variable tells which Python library libshiboken was linked against. --- CMakeLists.txt | 4 +++- data/ShibokenConfig.cmake.in | 10 ++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dab1888b..dc4c8348 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,7 +26,7 @@ if(MSVC) set(CMAKE_CXX_FLAGS "/Zc:wchar_t- /GR /EHsc /DWIN32 /D_WINDOWS /D_SCL_SECURE_NO_WARNINGS") else() if(CMAKE_HOST_UNIX) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fvisibility=hidden -Wno-strict-aliasing") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -fvisibility=hidden -Wno-strict-aliasing") endif() set(CMAKE_CXX_FLAGS_DEBUG "-g") option(ENABLE_GCC_OPTIMIZATION "Enable specific GCC flags to optimization library size and performance. Only available on Release Mode" 0) @@ -69,6 +69,7 @@ execute_process( OUTPUT_VARIABLE PY_DEBUG OUTPUT_STRIP_TRAILING_WHITESPACE) +set(SHIBOKEN_BUILD_TYPE "Release") if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(NOT PYTHON_DEBUG_LIBRARIES) message(FATAL_ERROR "Python debug library not found. Try compile shiboken with -DCMAKE_BUILD_TYPE=Release") @@ -79,6 +80,7 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug") add_definitions("-DPy_DEBUG") endif() set(SBK_PYTHON_LIBRARIES ${PYTHON_DEBUG_LIBRARIES}) + set(SHIBOKEN_BUILD_TYPE "Debug") else() set(SBK_PYTHON_LIBRARIES ${PYTHON_LIBRARIES}) add_definitions("-DNDEBUG") diff --git a/data/ShibokenConfig.cmake.in b/data/ShibokenConfig.cmake.in index 8d46e76a..367ac5c0 100644 --- a/data/ShibokenConfig.cmake.in +++ b/data/ShibokenConfig.cmake.in @@ -1,5 +1,8 @@ -# SHIBOKEN_INCLUDE_DIR - Directories to include to use SHIBOKEN -# SHIBOKEN_LIBRARIES - Files to link against to use SHIBOKEN +# SHIBOKEN_INCLUDE_DIR - Directories to include to use SHIBOKEN +# SHIBOKEN_LIBRARIES - Files to link against to use SHIBOKEN +# SHIBOKEN_BUILD_TYPE - Tells if Shiboken was compiled in Release or Debug mode. +# SHIBOKEN_PYTHON_INTERPRETER - Python interpreter (regular or debug) to be used with the bindings. +# SHIBOKEN_PYTHON_LIBRARIES - Python libraries (regular or debug) Shiboken is linked against. SET(SHIBOKEN_INCLUDE_DIR "@CMAKE_INSTALL_PREFIX@/include/shiboken@shiboken_SUFFIX@") if(MSVC) @@ -9,3 +12,6 @@ elseif(WIN32) else() SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") endif() +SET(SHIBOKEN_BUILD_TYPE "@SHIBOKEN_BUILD_TYPE@") +SET(SHIBOKEN_PYTHON_INTERPRETER "@PYTHON_EXECUTABLE@") +SET(SHIBOKEN_PYTHON_LIBRARIES "@SBK_PYTHON_LIBRARIES@") From 839d7efb8f42e732cfab043ba74384f52502e70b Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Wed, 20 Oct 2010 16:31:49 -0300 Subject: [PATCH 073/564] Fixes libshiboken pkg-config file. --- data/shiboken.pc.in | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/data/shiboken.pc.in b/data/shiboken.pc.in index 0b3bdfd4..75d8578b 100644 --- a/data/shiboken.pc.in +++ b/data/shiboken.pc.in @@ -3,10 +3,11 @@ exec_prefix=@CMAKE_INSTALL_PREFIX@ libdir=@LIB_INSTALL_DIR@ includedir=@CMAKE_INSTALL_PREFIX@/include/shiboken generator_location=@CMAKE_INSTALL_PREFIX@/bin/shiboken +python_interpreter=@PYTHON_EXECUTABLE@ Name: shiboken Description: Support library for Python bindings created with Shiboken generator. Version: @shiboken_VERSION@ -Libs: -L${libdir} -lpython -lshiboken@shiboken_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@ -Cflags: -I${includedir}/shiboken@shiboken_SUFFIX@ +Libs: @SBK_PYTHON_LIBRARIES@ -L${libdir} -lshiboken@shiboken_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@ +Cflags: -I@PYTHON_INCLUDE_PATH@ -I${includedir}/@shiboken_SUFFIX@ From 9d479c812d4e2e6fc427f96af4ce4f415c8eab0a Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Mon, 25 Oct 2010 18:25:50 -0300 Subject: [PATCH 074/564] libshiboken now sets debug flags for all modules linking against it. The information was added to cmake and pkg-config files. Reviewed by Lauro Moura Reviewed by Renato Araujo --- CMakeLists.txt | 3 +++ data/ShibokenConfig.cmake.in | 4 +++- data/shiboken.pc.in | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dc4c8348..a0a4469d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -78,6 +78,8 @@ if(CMAKE_BUILD_TYPE STREQUAL "Debug") message(WARNING "Compiling shiboken with debug enabled, but the python executable was not compiled with debug support.") else() add_definitions("-DPy_DEBUG") + set(SBK_ADD_PY_DEBUG_DEFINITION "add_definitions(\"-DPy_DEBUG\")") + set(SBK_PKG_CONFIG_PY_DEBUG_DEFINITION " -DPy_DEBUG") endif() set(SBK_PYTHON_LIBRARIES ${PYTHON_DEBUG_LIBRARIES}) set(SHIBOKEN_BUILD_TYPE "Debug") @@ -90,6 +92,7 @@ if(APPLE) endif() + if (BUILD_TESTS) enable_testing() endif() diff --git a/data/ShibokenConfig.cmake.in b/data/ShibokenConfig.cmake.in index 367ac5c0..2b9a3a09 100644 --- a/data/ShibokenConfig.cmake.in +++ b/data/ShibokenConfig.cmake.in @@ -12,6 +12,8 @@ elseif(WIN32) else() SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") endif() -SET(SHIBOKEN_BUILD_TYPE "@SHIBOKEN_BUILD_TYPE@") SET(SHIBOKEN_PYTHON_INTERPRETER "@PYTHON_EXECUTABLE@") SET(SHIBOKEN_PYTHON_LIBRARIES "@SBK_PYTHON_LIBRARIES@") +SET(SHIBOKEN_BUILD_TYPE "@SHIBOKEN_BUILD_TYPE@") +message("libshiboken built for @SHIBOKEN_BUILD_TYPE@") +@SBK_ADD_PY_DEBUG_DEFINITION@ diff --git a/data/shiboken.pc.in b/data/shiboken.pc.in index 75d8578b..4140f16e 100644 --- a/data/shiboken.pc.in +++ b/data/shiboken.pc.in @@ -9,5 +9,5 @@ Name: shiboken Description: Support library for Python bindings created with Shiboken generator. Version: @shiboken_VERSION@ Libs: @SBK_PYTHON_LIBRARIES@ -L${libdir} -lshiboken@shiboken_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@ -Cflags: -I@PYTHON_INCLUDE_PATH@ -I${includedir}/@shiboken_SUFFIX@ +Cflags: -I@PYTHON_INCLUDE_PATH@ -I${includedir}/@shiboken_SUFFIX@@SBK_PKG_CONFIG_PY_DEBUG_DEFINITION@ From 633cec7ee29bc130d6af9341a505a2b7377e755b Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Tue, 26 Oct 2010 13:47:55 -0300 Subject: [PATCH 075/564] Added the AVOID_PROTECTED_HACK option to the Shiboken cmake configuration file. Reviewed by Lauro Moura Reviewed by Luciano Wolf --- data/ShibokenConfig.cmake.in | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/data/ShibokenConfig.cmake.in b/data/ShibokenConfig.cmake.in index 2b9a3a09..2a4ffd4d 100644 --- a/data/ShibokenConfig.cmake.in +++ b/data/ShibokenConfig.cmake.in @@ -15,5 +15,11 @@ endif() SET(SHIBOKEN_PYTHON_INTERPRETER "@PYTHON_EXECUTABLE@") SET(SHIBOKEN_PYTHON_LIBRARIES "@SBK_PYTHON_LIBRARIES@") SET(SHIBOKEN_BUILD_TYPE "@SHIBOKEN_BUILD_TYPE@") -message("libshiboken built for @SHIBOKEN_BUILD_TYPE@") +message(STATUS "libshiboken built for @SHIBOKEN_BUILD_TYPE@") @SBK_ADD_PY_DEBUG_DEFINITION@ + +option(AVOID_PROTECTED_HACK "Avoid protected hack on generated bindings." FALSE) +if(AVOID_PROTECTED_HACK OR WIN32) + add_definitions(-DAVOID_PROTECTED_HACK) + message(STATUS "Avoiding protected hack!") +endif() From a91a1dad8abaeb71783b9ba26c8d2fb6d2a22eef Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 26 Oct 2010 15:10:55 -0200 Subject: [PATCH 076/564] Add variable with python include dir to ShibokenConfig.cmake MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Lauro Moura Renato Araújo --- data/ShibokenConfig.cmake.in | 1 + data/shiboken.pc.in | 1 + 2 files changed, 2 insertions(+) diff --git a/data/ShibokenConfig.cmake.in b/data/ShibokenConfig.cmake.in index 2a4ffd4d..bd39b39a 100644 --- a/data/ShibokenConfig.cmake.in +++ b/data/ShibokenConfig.cmake.in @@ -12,6 +12,7 @@ elseif(WIN32) else() SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") endif() +SET(SHIBOKEN_PYTHON_INCLUDE_DIR "@PYTHON_INCLUDE_DIR@") SET(SHIBOKEN_PYTHON_INTERPRETER "@PYTHON_EXECUTABLE@") SET(SHIBOKEN_PYTHON_LIBRARIES "@SBK_PYTHON_LIBRARIES@") SET(SHIBOKEN_BUILD_TYPE "@SHIBOKEN_BUILD_TYPE@") diff --git a/data/shiboken.pc.in b/data/shiboken.pc.in index 4140f16e..5fb4ab0d 100644 --- a/data/shiboken.pc.in +++ b/data/shiboken.pc.in @@ -4,6 +4,7 @@ libdir=@LIB_INSTALL_DIR@ includedir=@CMAKE_INSTALL_PREFIX@/include/shiboken generator_location=@CMAKE_INSTALL_PREFIX@/bin/shiboken python_interpreter=@PYTHON_EXECUTABLE@ +python_include_dir=@PYTHON_INCLUDE_DIR@ Name: shiboken Description: Support library for Python bindings created with Shiboken generator. From 65e55dba0ff70976e67d8c46699a6ca629ef4bf0 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Tue, 26 Oct 2010 15:38:21 -0300 Subject: [PATCH 077/564] Release gil before call C++ function on virtual method. Fixes bug #423. Reviewer: Hugo Parente Lima Luciano Wolf --- generator/cppgenerator.cpp | 4 ++-- libshiboken/gilstate.cpp | 8 ++++++-- libshiboken/gilstate.h | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 051af21c..fe9ea5c3 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -532,6 +532,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu s << INDENT << "if (py_override.isNull()) {" << endl; { Indentation indentation(INDENT); + s << INDENT << "gil.release();" << endl; CodeSnipList snips; if (func->hasInjectedCode()) { @@ -554,8 +555,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu s << INDENT << "Shiboken::ThreadStateSaver " THREAD_STATE_SAVER_VAR ";" << endl; s << INDENT << THREAD_STATE_SAVER_VAR ".save();" << endl; } - - s << INDENT << "return this->::" << func->implementingClass()->qualifiedCppName() << "::"; + s << "return this->::" << func->implementingClass()->qualifiedCppName() << "::"; writeFunctionCall(s, func, Generator::VirtualCall); } } diff --git a/libshiboken/gilstate.cpp b/libshiboken/gilstate.cpp index 50a3c6e6..f49930e1 100644 --- a/libshiboken/gilstate.cpp +++ b/libshiboken/gilstate.cpp @@ -33,10 +33,14 @@ GilState::GilState() GilState::~GilState() { - if(Py_IsInitialized()) - PyGILState_Release(m_gstate); + release(); } +void GilState::release() +{ + if(Py_IsInitialized() && m_gstate) + PyGILState_Release(m_gstate); +} } // namespace Shiboken diff --git a/libshiboken/gilstate.h b/libshiboken/gilstate.h index efb3cb79..b2f33cb2 100644 --- a/libshiboken/gilstate.h +++ b/libshiboken/gilstate.h @@ -34,6 +34,7 @@ class LIBSHIBOKEN_API GilState public: GilState(); ~GilState(); + void release(); private: PyGILState_STATE m_gstate; }; From b5cf0972d59ba2bf7df99b73a0b2b0c253aae09f Mon Sep 17 00:00:00 2001 From: renatofilho Date: Tue, 26 Oct 2010 15:40:09 -0300 Subject: [PATCH 078/564] Removed unnecessary cast on copy function. Reviewer: Hugo Parente Lima Luciano Wolf --- libshiboken/conversions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index 1dbc1840..f393dfbf 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -90,7 +90,7 @@ struct CppObjectCopier { static inline T* copy(const T& obj) { - return new T(*reinterpret_cast(&obj)); + return new T(obj); } }; From 4bc7a3822af0476ffc8a86ffac65775c46d6b4da Mon Sep 17 00:00:00 2001 From: renatofilho Date: Wed, 27 Oct 2010 17:10:24 -0300 Subject: [PATCH 079/564] Fixed GilState and ThreadSave code generation. Reviewer: Luciano Wolf Marcelo Lira --- generator/cppgenerator.cpp | 9 ++------- libshiboken/gilstate.cpp | 8 ++++++-- libshiboken/gilstate.h | 1 + 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index fe9ea5c3..7f708d20 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -532,8 +532,6 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu s << INDENT << "if (py_override.isNull()) {" << endl; { Indentation indentation(INDENT); - s << INDENT << "gil.release();" << endl; - CodeSnipList snips; if (func->hasInjectedCode()) { snips = func->injectedCodeSnips(); @@ -551,11 +549,8 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu s << defaultReturnExpr; } } else { - if (func->allowThread()) { - s << INDENT << "Shiboken::ThreadStateSaver " THREAD_STATE_SAVER_VAR ";" << endl; - s << INDENT << THREAD_STATE_SAVER_VAR ".save();" << endl; - } - s << "return this->::" << func->implementingClass()->qualifiedCppName() << "::"; + s << INDENT << "gil.release();" << endl; + s << INDENT << "return this->::" << func->implementingClass()->qualifiedCppName() << "::"; writeFunctionCall(s, func, Generator::VirtualCall); } } diff --git a/libshiboken/gilstate.cpp b/libshiboken/gilstate.cpp index f49930e1..cc8963ff 100644 --- a/libshiboken/gilstate.cpp +++ b/libshiboken/gilstate.cpp @@ -27,8 +27,10 @@ namespace Shiboken GilState::GilState() { - if(Py_IsInitialized()) + if(Py_IsInitialized()) { m_gstate = PyGILState_Ensure(); + m_locked = true; + } } GilState::~GilState() @@ -38,8 +40,10 @@ GilState::~GilState() void GilState::release() { - if(Py_IsInitialized() && m_gstate) + if(m_locked && Py_IsInitialized()) { PyGILState_Release(m_gstate); + m_locked = false; + } } } // namespace Shiboken diff --git a/libshiboken/gilstate.h b/libshiboken/gilstate.h index b2f33cb2..f67e6959 100644 --- a/libshiboken/gilstate.h +++ b/libshiboken/gilstate.h @@ -37,6 +37,7 @@ class LIBSHIBOKEN_API GilState void release(); private: PyGILState_STATE m_gstate; + bool m_locked; }; } // namespace Shiboken From 016bc9ba8847411cb92ee25a03d50e62f4e9e952 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Wed, 27 Oct 2010 17:11:03 -0300 Subject: [PATCH 080/564] Implemented support to conversion without memory allocation. Reviewer: Luciano Wolf Marcelo Lira --- libshiboken/typeresolver.cpp | 14 +++++++------- libshiboken/typeresolver.h | 18 +++++++++++------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/libshiboken/typeresolver.cpp b/libshiboken/typeresolver.cpp index 89bc6329..3d0cb11a 100644 --- a/libshiboken/typeresolver.cpp +++ b/libshiboken/typeresolver.cpp @@ -97,14 +97,9 @@ const char* TypeResolver::typeName() const return m_d->typeName; } -void* TypeResolver::toCpp(PyObject* pyObj) +void* TypeResolver::toCpp(PyObject* pyObj, void** place, bool alloc) { - return m_d->pythonToCpp(pyObj); -} - -PyObject* TypeResolver::toPython(void* cppObj) -{ - return m_d->cppToPython(cppObj); + return m_d->pythonToCpp(pyObj, place, alloc); } void TypeResolver::deleteObject(void* object) @@ -113,6 +108,11 @@ void TypeResolver::deleteObject(void* object) m_d->deleteObject(object); } +PyObject* TypeResolver::toPython(void* cppObj) +{ + return m_d->cppToPython(cppObj); +} + PyTypeObject* TypeResolver::pythonType() { return m_d->pyType; diff --git a/libshiboken/typeresolver.h b/libshiboken/typeresolver.h index 18593551..b11678e2 100644 --- a/libshiboken/typeresolver.h +++ b/libshiboken/typeresolver.h @@ -33,15 +33,20 @@ class SbkBaseWrapperType; /* To C++ convertion functions. */ template -inline void* pythonToValueType(PyObject* pyobj) +inline void* pythonToValueType(PyObject* pyobj, void** data, bool alloc) { - return Shiboken::CppObjectCopier::copy(Shiboken::Converter::toCpp(pyobj)); + if (alloc) + *data = Shiboken::CppObjectCopier::copy(Shiboken::Converter::toCpp(pyobj)); + + *reinterpret_cast< T*>(*data) = Shiboken::Converter::toCpp(pyobj); + return *data; } template -inline void* pythonToObjectType(PyObject* pyobj) +inline void* pythonToObjectType(PyObject* pyobj, void** data, bool) { - return Shiboken::Converter::toCpp(pyobj); + *data = Shiboken::Converter::toCpp(pyobj); + return *data; } template @@ -73,9 +78,8 @@ class LIBSHIBOKEN_API TypeResolver }; typedef PyObject* (*CppToPythonFunc)(void*); - typedef void* (*PythonToCppFunc)(PyObject*); + typedef void* (*PythonToCppFunc)(PyObject*, void**, bool); typedef void (*DeleteObjectFunc)(void*); - typedef PyTypeObject* (*GetPyTypeFunc)(); ~TypeResolver(); @@ -96,7 +100,7 @@ class LIBSHIBOKEN_API TypeResolver const char* typeName() const; PyObject* toPython(void* cppObj); - void* toCpp(PyObject* pyObj); + void* toCpp(PyObject* pyObj, void** place, bool alloc=false); void deleteObject(void* object); PyTypeObject* pythonType(); From b146f4117c676a6a65b1e29a09d5f6c86541cd0d Mon Sep 17 00:00:00 2001 From: renatofilho Date: Thu, 28 Oct 2010 13:46:41 -0300 Subject: [PATCH 081/564] Implemented support to dynamic signals created on QML side. Fixes bug #437. Reviewer: Marcelo Lira Luciano Wolf --- generator/cppgenerator.cpp | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 7f708d20..02ca2dda 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -3556,7 +3556,7 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, const AbstractMetaClass s << INDENT << '}' << endl; } s << INDENT << "PyObject* attr = PyObject_GenericGetAttr(self, name);" << endl; - if (usePySideExtensions() && metaClass->isQObject()) { + if (usePySideExtensions() && (metaClass->qualifiedCppName() == "QObject")) { s << INDENT << "if (attr && PySide::isQPropertyType(attr)) {" << endl; { Indentation indent(INDENT); @@ -3571,7 +3571,39 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, const AbstractMetaClass s << INDENT << "attr = value;" << endl; } s << INDENT << "}" << endl; + + s << INDENT << "//search on metaobject (avoid internal attributes started with '__')" << endl + << INDENT << "if (!attr && !QString(PyString_AS_STRING(name)).startsWith(\"__\")) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "QObject* cppSelf = Converter::toCpp(self);" << endl + << INDENT << "const QMetaObject* metaObject = cppSelf->metaObject();" << endl + << INDENT << "QByteArray cname(PyString_AS_STRING(name));" << endl + << INDENT << "cname += '(';" << endl + << INDENT << "//signal" << endl + << INDENT << "QList signalList;" << endl + << INDENT << "for(int i=0, i_max = metaObject->methodCount(); i < i_max; i++) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "QMetaMethod method = metaObject->method(i);" << endl + << INDENT << "if ((method.methodType() == QMetaMethod::Signal) &&" << endl + << INDENT << "QString(method.signature()).startsWith(cname))" << endl + << INDENT << "signalList.append(method);" << endl; + } + s << INDENT << "}" << endl + << INDENT << "if (signalList.size() > 0) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyObject* pySignal = PySide::signalNewFromMethod(self, signalList);" << endl + << INDENT << "PyObject_SetAttr(self, name, pySignal);" << endl + << INDENT << "PyObject_GenericSetAttr(self, name, pySignal);" << endl + << INDENT << "return pySignal;" << endl; + } + s << INDENT << "}" << endl; + } + s << INDENT << "}" << endl; } + s << INDENT << "return attr;" << endl; s << '}' << endl; } From 45f10c2264bef5c25e493bb6f70ef6355a7f94d1 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 27 Oct 2010 19:45:19 -0200 Subject: [PATCH 082/564] Write copy constructor for Object types when there is one. --- generator/headergenerator.cpp | 11 +++++------ tests/libsample/reference.h | 2 ++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/generator/headergenerator.cpp b/generator/headergenerator.cpp index 39db3c6e..12d246a1 100644 --- a/generator/headergenerator.cpp +++ b/generator/headergenerator.cpp @@ -91,9 +91,6 @@ void HeaderGenerator::generateClass(QTextStream& s, const AbstractMetaClass* met s << endl << '{' << endl << "public:" << endl; - if (metaClass->typeEntry()->isValue()) - writeCopyCtor(s, metaClass); - bool hasVirtualFunction = false; foreach (AbstractMetaFunction *func, filterFunctions(metaClass)) { if (func->isVirtual()) @@ -142,11 +139,13 @@ void HeaderGenerator::generateClass(QTextStream& s, const AbstractMetaClass* met void HeaderGenerator::writeFunction(QTextStream& s, const AbstractMetaFunction* func) const { + // do not write copy ctors here. - if (func->isCopyConstructor()) + if (!func->isPrivate() && func->isCopyConstructor()) { + writeCopyCtor(s, func->ownerClass()); return; - - if (func->isConstructor() && func->isUserAdded()) + } + if (func->isUserAdded()) return; #ifdef AVOID_PROTECTED_HACK diff --git a/tests/libsample/reference.h b/tests/libsample/reference.h index cc9fcc91..54360d88 100644 --- a/tests/libsample/reference.h +++ b/tests/libsample/reference.h @@ -60,6 +60,8 @@ class LIBSAMPLE_API Reference class LIBSAMPLE_API ObjTypeReference { public: + ObjTypeReference() {} + ObjTypeReference(const ObjTypeReference&) {} virtual ~ObjTypeReference(); virtual ObjTypeReference& returnMyFirstArg(ObjTypeReference& ref) { return ref; } virtual ObjTypeReference& returnMySecondArg(int a, ObjTypeReference& ref) { return ref; } From aee6f385b5ffbed54df2e18ece072a7cc3281768 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 27 Oct 2010 15:56:58 -0200 Subject: [PATCH 083/564] Simplifies the generated code removing the use of std::auto_ptr. --- generator/cppgenerator.cpp | 118 +++++++++----------------------- generator/cppgenerator.h | 8 +-- generator/shibokengenerator.cpp | 4 -- libshiboken/conversions.h | 6 +- tests/libsample/echo.h | 2 + 5 files changed, 41 insertions(+), 97 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 02ca2dda..32ee06d8 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -1463,9 +1463,9 @@ void CppGenerator::writeTypeCheck(QTextStream& s, const OverloadData* overloadDa void CppGenerator::writeArgumentConversion(QTextStream& s, const AbstractMetaType* argType, - QString argName, QString pyArgName, + const QString& argName, const QString& pyArgName, const AbstractMetaClass* context, - QString defaultValue) + const QString& defaultValue) { const TypeEntry* type = argType->typeEntry(); @@ -1475,69 +1475,38 @@ void CppGenerator::writeArgumentConversion(QTextStream& s, QString typeName; QString baseTypeName = type->name(); bool isWrappedCppClass = type->isValue() || type->isObject(); - if (isWrappedCppClass) - typeName = baseTypeName + '*'; - else - typeName = translateTypeForWrapperMethod(argType, context); - if (type->isContainer() || type->isPrimitive()) { - // If the type is a const char*, we don't remove the "const". - if (typeName.startsWith("const ") && !(isCString(argType))) - typeName.remove(0, sizeof("const ") / sizeof(char) - 1); - if (typeName.endsWith("&")) - typeName.chop(1); - } - typeName = typeName.trimmed(); + // exclude const on Objects + Options flags; + bool isCStr = isCString(argType); + if (argType->indirections() && !isCStr) + flags = ExcludeConst; + else if (type->isPrimitive() && !isCStr) + flags = ExcludeConst | ExcludeReference; + else if (type->isValue() && argType->isConstant() && argType->isReference()) + flags = ExcludeConst | ExcludeReference; // const refs become just the value, but pure refs must remain pure. - bool hasImplicitConversions = !implicitConversions(argType).isEmpty(); - - if (isWrappedCppClass) { - const TypeEntry* typeEntry = (hasImplicitConversions ? type : 0); - writeInvalidCppObjectCheck(s, pyArgName, typeEntry); - } + typeName = translateTypeForWrapperMethod(argType, context, flags).trimmed(); - // Auto pointer to dealloc new objects created because to satisfy implicit conversion. - if (hasImplicitConversions) - s << INDENT << "std::auto_ptr<" << baseTypeName << " > " << argName << "_auto_ptr;" << endl; + if (isWrappedCppClass) + writeInvalidCppObjectCheck(s, pyArgName, 0); // Value type that has default value. if (argType->isValue() && !defaultValue.isEmpty()) s << INDENT << baseTypeName << ' ' << argName << "_tmp = " << defaultValue << ';' << endl; - if (usePySideExtensions() && typeName == "QStringRef") { - s << INDENT << "QString " << argName << "_qstring = "; - if (!defaultValue.isEmpty()) - s << pyArgName << " ? "; - s << "Shiboken::Converter::toCpp(" << pyArgName << ')' << endl; - if (!defaultValue.isEmpty()) - s << " : " << defaultValue; - s << ';' << endl; - s << INDENT << "QStringRef " << argName << "(&" << argName << "_qstring);" << endl; - } else { - s << INDENT << typeName << ' ' << argName << " = "; - if (!defaultValue.isEmpty()) - s << pyArgName << " ? "; - s << "Shiboken::Converter<" << typeName << " >::toCpp(" << pyArgName << ')'; - if (!defaultValue.isEmpty()) { - s << " : "; - if (argType->isValue()) - s << '&' << argName << "_tmp"; - else - s << defaultValue; - } - s << ';' << endl; - } - - if (hasImplicitConversions) { - s << INDENT << "if ("; - if (!defaultValue.isEmpty()) - s << pyArgName << " && "; - s << '!' << cpythonCheckFunction(type) << '(' << pyArgName << "))"; - s << endl; - Indentation indent(INDENT); - s << INDENT << argName << "_auto_ptr = std::auto_ptr<" << baseTypeName; - s << " >(" << argName << ");" << endl; + s << INDENT << typeName << ' ' << argName << " = "; + if (!defaultValue.isEmpty()) + s << pyArgName << " ? "; + s << "Shiboken::Converter<" << typeName << " >::toCpp(" << pyArgName << ')'; + if (!defaultValue.isEmpty()) { + s << " : "; + if (argType->isValue()) + s << argName << "_tmp"; + else + s << defaultValue; } + s << ';' << endl; } void CppGenerator::writeNoneReturn(QTextStream& s, const AbstractMetaFunction* func, bool thereIsReturnValue) @@ -1962,8 +1931,6 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f argName = arg->name() + "_out"; } else { argName = QString("cpp_arg%1").arg(idx); - if (shouldDereferenceArgumentPointer(arg)) - argName.prepend('*'); } userArgs << argName; } @@ -2015,7 +1982,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f QString firstArg("(*" CPP_SELF_VAR ")"); QString secondArg("cpp_arg0"); if (!func->isUnaryOperator() && shouldDereferenceArgumentPointer(func->arguments().first())) { - secondArg.prepend("(*"); + secondArg.prepend('('); secondArg.append(')'); } @@ -2038,11 +2005,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f QString className = wrapperName(func->ownerClass()); mc << "new " << className << '('; if (func->isCopyConstructor() && maxArgs == 1) { - mc << '*'; - QString arg("cpp_arg0"); - if (shouldGenerateCppWrapper(func->ownerClass())) - arg = QString("reinterpret_cast<%1*>(%2)").arg(className).arg(arg); - mc << arg; + mc << "cpp_arg0"; } else { mc << userArgs.join(", "); } @@ -2844,28 +2807,11 @@ void CppGenerator::writeRichCompareFunction(QTextStream& s, const AbstractMetaCl Indentation indent(INDENT); s << INDENT << "// " << func->signature() << endl; s << INDENT; - AbstractMetaClass* clz = classes().findClass(type->typeEntry()); - if (type->typeEntry()->isValue()) { - Q_ASSERT(clz); - s << clz->qualifiedCppName() << '*'; - } else - s << translateTypeForWrapperMethod(type, metaClass); + s << translateTypeForWrapperMethod(type, metaClass, ExcludeReference | ExcludeConst); s << " cpp_other = "; - if (type->typeEntry()->isValue()) - s << cpythonWrapperCPtr(type, "other"); - else - writeToCppConversion(s, type, metaClass, "other"); + writeToCppConversion(s, type, metaClass, "other", ExcludeReference | ExcludeConst); s << ';' << endl; - - s << INDENT << "result = "; - // It's a value type and the conversion for a pointer returned null. - if (type->typeEntry()->isValue()) { - s << "!cpp_other ? cpp_self == "; - writeToCppConversion(s, type, metaClass, "other", ExcludeReference | ExcludeConst); - s << " : "; - } - s << "(cpp_self " << op << ' ' << (type->typeEntry()->isValue() ? "(*" : ""); - s << "cpp_other" << (type->typeEntry()->isValue() ? ")" : "") << ");" << endl; + s << INDENT << "result = (cpp_self " << op << " cpp_other);" << endl; } s << INDENT << '}'; } @@ -2874,7 +2820,7 @@ void CppGenerator::writeRichCompareFunction(QTextStream& s, const AbstractMetaCl if (comparesWithSameType && !metaClass->implicitConversions().isEmpty()) { AbstractMetaType temporaryType; temporaryType.setTypeEntry(metaClass->typeEntry()); - temporaryType.setConstant(true); + temporaryType.setConstant(false); temporaryType.setReference(false); temporaryType.setTypeUsagePattern(AbstractMetaType::ValuePattern); s << " else if (" << cpythonIsConvertibleFunction(metaClass->typeEntry()); @@ -2882,7 +2828,7 @@ void CppGenerator::writeRichCompareFunction(QTextStream& s, const AbstractMetaCl { Indentation indent(INDENT); writeArgumentConversion(s, &temporaryType, "cpp_other", "other", metaClass); - s << INDENT << "result = (cpp_self " << op << " (*cpp_other));" << endl; + s << INDENT << "result = (cpp_self " << op << " cpp_other);" << endl; } s << INDENT << '}'; } diff --git a/generator/cppgenerator.h b/generator/cppgenerator.h index b356ca87..645f63fd 100644 --- a/generator/cppgenerator.h +++ b/generator/cppgenerator.h @@ -83,14 +83,14 @@ class CppGenerator : public ShibokenGenerator * \param defaultValue an optional default value to be used instead of the conversion result */ void writeArgumentConversion(QTextStream& s, const AbstractMetaType* argType, - QString argName, QString pyArgName, + const QString& argName, const QString& pyArgName, const AbstractMetaClass* context = 0, - QString defaultValue = QString()); + const QString& defaultValue = QString()); /// Convenience method to call writeArgumentConversion with an AbstractMetaArgument instead of an AbstractMetaType. void writeArgumentConversion(QTextStream& s, const AbstractMetaArgument* arg, - QString argName, QString pyArgName, + const QString& argName, const QString& pyArgName, const AbstractMetaClass* context = 0, - QString defaultValue = QString()) + const QString& defaultValue = QString()) { writeArgumentConversion(s, arg->type(), argName, pyArgName, context, defaultValue); } diff --git a/generator/shibokengenerator.cpp b/generator/shibokengenerator.cpp index a1606e85..aafa3c50 100644 --- a/generator/shibokengenerator.cpp +++ b/generator/shibokengenerator.cpp @@ -1209,8 +1209,6 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, argReplacement = usePyArgs ? QString("pyargs[%1]").arg(i - removed) : "arg"; } else { argReplacement = QString("cpp_arg%1").arg(i - removed); - if (shouldDereferenceArgumentPointer(arg)) - argReplacement.prepend("(*").append(')'); } } } else { @@ -1236,8 +1234,6 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, argName = arg->defaultValueExpression(); } else { argName = QString("cpp_arg%1").arg(arg->argumentIndex() - removed); - if (shouldDereferenceArgumentPointer(arg)) - argName.prepend('*'); } argumentNames << argName; } else { diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index f393dfbf..475902ea 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -234,14 +234,14 @@ struct ValueTypeConverter // use them if it is the case. static inline T toCpp(PyObject* pyobj) { - PyTypeObject* typeObj = SbkType(); - if (typeObj->ob_type == &Shiboken::SbkBaseWrapperType_Type) { - SbkBaseWrapperType* shiboType = reinterpret_cast(typeObj); + if (!PyObject_TypeCheck(pyobj, SbkType())) { + SbkBaseWrapperType* shiboType = reinterpret_cast(SbkType()); if (shiboType->ext_tocpp && isConvertible(pyobj)) { T* cptr = reinterpret_cast(shiboType->ext_tocpp(pyobj)); std::auto_ptr cptr_auto_ptr(cptr); return *cptr; } + assert(false); } return *reinterpret_cast(getCppPointer(pyobj, SbkType())); } diff --git a/tests/libsample/echo.h b/tests/libsample/echo.h index 3e607cdd..40aed304 100644 --- a/tests/libsample/echo.h +++ b/tests/libsample/echo.h @@ -33,6 +33,8 @@ class Echo Echo(){} ~Echo(){} + void doNothingWithConstBool(const bool hi) {} + // These method are here just for compilation test purposes Echo& operator<<(unsigned int item) { return *this; } Echo& operator<<(signed int item) { return *this; } From 6de649a4f272bb98048602738af511d102cd5209 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 28 Oct 2010 15:00:59 -0200 Subject: [PATCH 084/564] Uses a constant to define the cpp_arg variable, now called cppArg. --- generator/cppgenerator.cpp | 8 ++++---- generator/shibokengenerator.cpp | 4 ++-- generator/shibokengenerator.h | 2 ++ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 32ee06d8..77c75187 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -1738,7 +1738,7 @@ void CppGenerator::writeSingleFunctionCall(QTextStream& s, const OverloadData& o argType = buildAbstractMetaTypeFromString(typeReplaced); if (argType) { - QString argName = QString("cpp_arg%1").arg(i - removedArgs); + QString argName = QString(CPP_ARG"%1").arg(i - removedArgs); QString pyArgName = usePyArgs ? QString("pyargs[%1]").arg(i - removedArgs) : "arg"; QString defaultValue = guessScopeForDefaultValue(func, arg); @@ -1930,7 +1930,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f if (hasConversionRule) { argName = arg->name() + "_out"; } else { - argName = QString("cpp_arg%1").arg(idx); + argName = QString(CPP_ARG"%1").arg(idx); } userArgs << argName; } @@ -1980,7 +1980,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f } } else if (func->isOperatorOverload()) { QString firstArg("(*" CPP_SELF_VAR ")"); - QString secondArg("cpp_arg0"); + QString secondArg(CPP_ARG0); if (!func->isUnaryOperator() && shouldDereferenceArgumentPointer(func->arguments().first())) { secondArg.prepend('('); secondArg.append(')'); @@ -2005,7 +2005,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f QString className = wrapperName(func->ownerClass()); mc << "new " << className << '('; if (func->isCopyConstructor() && maxArgs == 1) { - mc << "cpp_arg0"; + mc << CPP_ARG0; } else { mc << userArgs.join(", "); } diff --git a/generator/shibokengenerator.cpp b/generator/shibokengenerator.cpp index aafa3c50..b93009e5 100644 --- a/generator/shibokengenerator.cpp +++ b/generator/shibokengenerator.cpp @@ -1208,7 +1208,7 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, if (arg->type()->typeEntry()->isCustom()) { argReplacement = usePyArgs ? QString("pyargs[%1]").arg(i - removed) : "arg"; } else { - argReplacement = QString("cpp_arg%1").arg(i - removed); + argReplacement = QString(CPP_ARG"%1").arg(i - removed); } } } else { @@ -1233,7 +1233,7 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, if (lastArg && arg->argumentIndex() > lastArg->argumentIndex()) { argName = arg->defaultValueExpression(); } else { - argName = QString("cpp_arg%1").arg(arg->argumentIndex() - removed); + argName = QString(CPP_ARG"%1").arg(arg->argumentIndex() - removed); } argumentNames << argName; } else { diff --git a/generator/shibokengenerator.h b/generator/shibokengenerator.h index 1a7c5a63..7695d112 100644 --- a/generator/shibokengenerator.h +++ b/generator/shibokengenerator.h @@ -28,6 +28,8 @@ #define CPP_RETURN_VAR "cppResult" #define THREAD_STATE_SAVER_VAR "threadStateSaver" #define CPP_SELF_VAR "cppSelf" +#define CPP_ARG "cppArg" +#define CPP_ARG0 (CPP_ARG "0") #include #include From 6b4655799df991b784979d9974680208a8766a8c Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 28 Oct 2010 15:03:38 -0200 Subject: [PATCH 085/564] Uses CPP_SELF_VAR macro and replaces cpp_other by cppOther. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Renato Araújo Marcelo Lira --- generator/cppgenerator.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 77c75187..f5043faf 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2759,7 +2759,7 @@ void CppGenerator::writeRichCompareFunction(QTextStream& s, const AbstractMetaCl s << '{' << endl; QList cmpOverloads = filterGroupedOperatorFunctions(metaClass, AbstractMetaClass::ComparisonOp); s << INDENT << "bool result = false;" << endl; - s << INDENT << metaClass->qualifiedCppName() << "& cpp_self = *" << cpythonWrapperCPtr(metaClass) << ';' << endl; + s << INDENT << metaClass->qualifiedCppName() << "& " CPP_SELF_VAR " = *" << cpythonWrapperCPtr(metaClass) << ';' << endl; s << endl; s << INDENT << "switch (op) {" << endl; @@ -2808,10 +2808,10 @@ void CppGenerator::writeRichCompareFunction(QTextStream& s, const AbstractMetaCl s << INDENT << "// " << func->signature() << endl; s << INDENT; s << translateTypeForWrapperMethod(type, metaClass, ExcludeReference | ExcludeConst); - s << " cpp_other = "; + s << " cppOther = "; writeToCppConversion(s, type, metaClass, "other", ExcludeReference | ExcludeConst); s << ';' << endl; - s << INDENT << "result = (cpp_self " << op << " cpp_other);" << endl; + s << INDENT << "result = (" CPP_SELF_VAR " " << op << " cppOther);" << endl; } s << INDENT << '}'; } @@ -2827,8 +2827,8 @@ void CppGenerator::writeRichCompareFunction(QTextStream& s, const AbstractMetaCl s << "(other)) {" << endl; { Indentation indent(INDENT); - writeArgumentConversion(s, &temporaryType, "cpp_other", "other", metaClass); - s << INDENT << "result = (cpp_self " << op << " cpp_other);" << endl; + writeArgumentConversion(s, &temporaryType, "cppOther", "other", metaClass); + s << INDENT << "result = (" CPP_SELF_VAR " " << op << " cppOther);" << endl; } s << INDENT << '}'; } From 8892aa211cb6c3986480abc251c66a494ada4ab9 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Thu, 28 Oct 2010 17:29:08 -0300 Subject: [PATCH 086/564] Fixed typesystem in function where is necessary thread save option. Reviewer: Hugo Parente Lima --- tests/samplebinding/typesystem_sample.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 0e9b16ca..60e7e22c 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -1200,6 +1200,7 @@ + From 5348af9f0700715fb4013886178d0915dd3fae80 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 29 Oct 2010 10:46:33 -0200 Subject: [PATCH 087/564] Bump version and package requirements. --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a0a4469d..f2c29a64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,8 +7,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules/ ${CMAKE_MODULE_PATH}) find_package(Qt4 4.5.0) -find_package(ApiExtractor 0.8) -find_package(GeneratorRunner 0.6.1) +find_package(ApiExtractor 0.8.2) +find_package(GeneratorRunner 0.6.3) find_package(PythonLibs) find_package(PythonInterpWithDebug) @@ -16,7 +16,7 @@ add_definitions(${QT_DEFINITIONS}) set(shiboken_MAJOR_VERSION "0") set(shiboken_MINOR_VERSION "5") -set(shiboken_MICRO_VERSION "1") +set(shiboken_MICRO_VERSION "2") set(shiboken_VERSION "${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VERSION}.${shiboken_MICRO_VERSION}") option(AVOID_PROTECTED_HACK "Avoid protected hack on generated bindings." FALSE) From 5c9f0f811e5d8eac4465b21a2255613aa9f543a7 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 29 Oct 2010 15:25:07 -0200 Subject: [PATCH 088/564] Fix function PySequenceToArgcArgv to support unicode strings. Also fix some reference leaks. Reviewer: Luciano Wolf Lauro Moura --- libshiboken/helper.cpp | 45 +++++++++++++++++++++++++++--------------- libshiboken/helper.h | 14 ++++++++++--- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/libshiboken/helper.cpp b/libshiboken/helper.cpp index f61fc144..c37c5432 100644 --- a/libshiboken/helper.cpp +++ b/libshiboken/helper.cpp @@ -27,33 +27,46 @@ namespace Shiboken bool PySequenceToArgcArgv(PyObject* argList, int* argc, char*** argv, const char* defaultAppName) +{ + return sequenceToArgcArgv(argList, argc, argv, defaultAppName); +} + +bool +sequenceToArgcArgv(PyObject* argList, int* argc, char*** argv, const char* defaultAppName) { if (!PySequence_Check(argList)) return false; + if (!defaultAppName) + defaultAppName = "PySideApplication"; + // Check all items - int numArgs = PySequence_Size(argList); - for (int i = 0; i < numArgs; ++i) - if (!PyString_Check(PySequence_GetItem(argList, i))) + Shiboken::AutoDecRef args(PySequence_Fast(argList, 0)); + int numArgs = PySequence_Fast_GET_SIZE(argList); + for (int i = 0; i < numArgs; ++i) { + PyObject* item = PySequence_Fast_GET_ITEM(args.object(), i); + if (!PyString_Check(item) && !PyUnicode_Check(item)) return false; + } - bool addAppName = !numArgs && defaultAppName; - *argc = addAppName ? 1 : numArgs; - + *argc = numArgs + 1; *argv = new char*[*argc]; for (int i = 0; i < numArgs; ++i) { - PyObject* item = PySequence_GetItem(argList, i); - char* string = PyString_AS_STRING(item); - int size = strlen(string); - (*argv)[i] = new char[size+1]; - (*argv)[i] = strcpy((*argv)[i], string); - Py_DECREF(item); + PyObject* item = PySequence_Fast_GET_ITEM(args.object(), i); + char* string; + if (PyUnicode_Check(item)) { + Shiboken::AutoDecRef utf8(PyUnicode_AsUTF8String(item)); + string = strdup(PyString_AS_STRING(utf8.object())); + } else { + string = strdup(PyString_AS_STRING(item)); + } + (*argv)[i+1] = string; } - if (addAppName) { - (*argv)[0] = new char[strlen(defaultAppName)+1]; - (*argv)[0] = strcpy((*argv)[0], defaultAppName); - } + // Try to get the script name + PyObject* globals = PyEval_GetGlobals(); + PyObject* appName = PyDict_GetItemString(globals, "__file__"); + (*argv)[0] = strdup(appName ? PyString_AS_STRING(appName) : defaultAppName); return true; } diff --git a/libshiboken/helper.h b/libshiboken/helper.h index 36340907..a0630412 100644 --- a/libshiboken/helper.h +++ b/libshiboken/helper.h @@ -67,12 +67,20 @@ inline PyObject* makeTuple(const A& a, const B& b, const C& c, const D& d, const /** * It transforms a python sequence into two C variables, argc and argv. -* If the sequence is empty and defaultAppName was provided, argc will be 1 and -* argv will have a copy of defaultAppName. +* This function tries to find the application (script) name and put it into argv[0], if +* the application name can't be guessed, defaultAppName will be used. * -* \note argc and argv *should* be deleted by the user. +* No memory is allocated is an error occur. +* +* \note argc must be a valid address. +* \note The argv array is allocated using new operator and each item is allocated using malloc. * \returns True on sucess, false otherwise. */ +LIBSHIBOKEN_API bool sequenceToArgcArgv(PyObject* argList, int* argc, char*** argv, const char* defaultAppName = 0); + +/** + * \deprecated Use sequenceToArgcArgv instead. + */ LIBSHIBOKEN_API bool PySequenceToArgcArgv(PyObject* argList, int* argc, char*** argv, const char* defaultAppName = 0); /** From 7ac0c10741046f9079b6fdced015140a4846e0c1 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Fri, 29 Oct 2010 14:03:24 -0300 Subject: [PATCH 089/564] Created utility function cast on AutoDecRef class. Reviewer: Hugo Parente Lima Marcelo Lira --- libshiboken/autodecref.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libshiboken/autodecref.h b/libshiboken/autodecref.h index b9c5d29f..20ed168d 100644 --- a/libshiboken/autodecref.h +++ b/libshiboken/autodecref.h @@ -52,6 +52,12 @@ class LIBSHIBOKEN_API AutoDecRef inline operator PyTupleObject*() { return reinterpret_cast(m_pyobj); } inline operator bool() const { return m_pyobj; } inline PyObject* operator->() { return m_pyobj; } + + template + T cast() + { + return reinterpret_cast(m_pyobj); + } private: PyObject* m_pyobj; AutoDecRef(const AutoDecRef&); From d09decc37b49ca19593131c7fb59486d5cfb1c33 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Fri, 29 Oct 2010 14:03:56 -0300 Subject: [PATCH 090/564] Implemented signal instantiation during the getattr function. Reviewer: Hugo Parente Lima Marcelo Lira --- generator/cppgenerator.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index f5043faf..d01beca9 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -3518,8 +3518,18 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, const AbstractMetaClass } s << INDENT << "}" << endl; - s << INDENT << "//search on metaobject (avoid internal attributes started with '__')" << endl - << INDENT << "if (!attr && !QString(PyString_AS_STRING(name)).startsWith(\"__\")) {" << endl; + //mutate native signals to signal instance type + s << INDENT << "if (attr && PyObject_TypeCheck(attr, &PySideSignalType)) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyObject* signal = reinterpret_cast(PySide::signalInitialize(attr, name, self));" << endl + << INDENT << "PyObject_SetAttr(self, name, signal);" << endl + << INDENT << "return signal;" << endl; + } + s << INDENT << "}" << endl; + + //search on metaobject (avoid internal attributes started with '__')"; + s << INDENT << "if (!attr && !QString(PyString_AS_STRING(name)).startsWith(\"__\")) {" << endl; { Indentation indent(INDENT); s << INDENT << "QObject* cppSelf = Converter::toCpp(self);" << endl From a53c92a42b29e0c49d28e0cf53f33b9515d78622 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 29 Oct 2010 16:31:33 -0200 Subject: [PATCH 091/564] Fix injectcode test to work with the newer version of sequencetoArgcArgv. --- tests/libsample/injectcode.cpp | 2 +- tests/samplebinding/typesystem_sample.xml | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/libsample/injectcode.cpp b/tests/libsample/injectcode.cpp index 05c4a143..6e19de75 100644 --- a/tests/libsample/injectcode.cpp +++ b/tests/libsample/injectcode.cpp @@ -54,7 +54,7 @@ const char* InjectCode::simpleMethod2() const char* InjectCode::simpleMethod3(int argc, char** argv) { - for (int i = 0; i < argc; ++i) + for (int i = 1; i < argc; ++i) m_valueHolder += argv[i]; return m_valueHolder.c_str(); } diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 60e7e22c..ff367f4c 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -914,7 +914,7 @@ int argc; char** argv; - if (!PySequenceToArgcArgv(%PYARG_1, &argc, &argv)) { + if (!sequenceToArgcArgv(%PYARG_1, &argc, &argv)) { PyErr_SetString(PyExc_TypeError, "error"); return 0; } @@ -922,7 +922,7 @@ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](foo); for (int i = 0; i < argc; ++i) - delete[] argv[i]; + free(argv[i]); delete[] argv; @@ -938,7 +938,7 @@ int argc; char** argv; - if (!PySequenceToArgcArgv(%PYARG_1, &argc, &argv)) { + if (!sequenceToArgcArgv(%PYARG_1, &argc, &argv)) { PyErr_SetString(PyExc_TypeError, "error"); return 0; } @@ -946,7 +946,7 @@ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](foo); for (int i = 0; i < argc; ++i) - delete[] argv[i]; + free(argv[i]); delete[] argv; From 6f6eabfc91d0b034be1b411c451dd1562519252d Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 29 Oct 2010 17:05:46 -0200 Subject: [PATCH 092/564] Don't use ref. on primitive types when using Converter::toPython. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Luciano Wolf Renato Araújo --- generator/cppgenerator.cpp | 10 +--------- generator/shibokengenerator.cpp | 25 +++++++++++++++++++++++-- generator/shibokengenerator.h | 5 +++++ 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index d01beca9..1ea5b15d 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -1477,15 +1477,7 @@ void CppGenerator::writeArgumentConversion(QTextStream& s, bool isWrappedCppClass = type->isValue() || type->isObject(); // exclude const on Objects - Options flags; - bool isCStr = isCString(argType); - if (argType->indirections() && !isCStr) - flags = ExcludeConst; - else if (type->isPrimitive() && !isCStr) - flags = ExcludeConst | ExcludeReference; - else if (type->isValue() && argType->isConstant() && argType->isReference()) - flags = ExcludeConst | ExcludeReference; // const refs become just the value, but pure refs must remain pure. - + Options flags = getConverterOptions(argType); typeName = translateTypeForWrapperMethod(argType, context, flags).trimmed(); if (isWrappedCppClass) diff --git a/generator/shibokengenerator.cpp b/generator/shibokengenerator.cpp index b93009e5..ee4ccd33 100644 --- a/generator/shibokengenerator.cpp +++ b/generator/shibokengenerator.cpp @@ -515,7 +515,10 @@ void ShibokenGenerator::writeToPythonConversion(QTextStream& s, const AbstractMe if (!type) return; - writeBaseConversion(s, type, context); + // exclude const on Objects + const TypeEntry* typeEntry = type->typeEntry(); + Options flags = getConverterOptions(type); + writeBaseConversion(s, type, context, flags); s << "toPython"; if (!argumentName.isEmpty()) @@ -789,7 +792,10 @@ QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* metaType } else { QString str; QTextStream s(&str); - writeBaseConversion(s, metaType, 0); + // exclude const on Objects + const TypeEntry* typeEntry = metaType->typeEntry(); + Options flags = getConverterOptions(metaType); + writeBaseConversion(s, metaType, 0, flags); s.flush(); return str + "checkType"; } @@ -1645,3 +1651,18 @@ bool ShibokenGenerator::pythonFunctionWrapperUsesListOfArguments(const OverloadD return usePyArgs; } +Generator::Options ShibokenGenerator::getConverterOptions(const AbstractMetaType* metaType) +{ + // exclude const on Objects + Options flags; + const TypeEntry* type = metaType->typeEntry(); + bool isCStr = isCString(metaType); + if (metaType->indirections() && !isCStr) + flags = ExcludeConst; + else if (type->isPrimitive() && !isCStr) + flags = ExcludeConst | ExcludeReference; + else if (type->isValue() && metaType->isConstant() && metaType->isReference()) + flags = ExcludeConst | ExcludeReference; // const refs become just the value, but pure refs must remain pure. + return flags; +} + diff --git a/generator/shibokengenerator.h b/generator/shibokengenerator.h index 7695d112..74396eb0 100644 --- a/generator/shibokengenerator.h +++ b/generator/shibokengenerator.h @@ -318,6 +318,11 @@ class ShibokenGenerator : public Generator */ AbstractMetaType* buildAbstractMetaTypeFromString(QString typeString); + /** + * Helper function to return the flags to be used by a meta type when + * it needs to write some converter code. + */ + static Options getConverterOptions(const AbstractMetaType* metaType); protected: bool doSetup(const QMap& args); // verify whether the class is copyable From 4e0e1c65ce2eb33ce83b5d6f94ad2ae59e53ca64 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Fri, 29 Oct 2010 16:15:12 -0300 Subject: [PATCH 093/564] Updated to new libpyside Signal/Slot namespace. Reviewer: Marcelo Lira Lauro Neto --- generator/cppgenerator.cpp | 15 +++++++-------- generator/headergenerator.cpp | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 1ea5b15d..428b1848 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -940,7 +940,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun // Create metaObject and register signal/slot if (metaClass->isQObject() && usePySideExtensions()) { s << endl << INDENT << "// QObject setup" << endl; - s << INDENT << "PySide::signalUpdateSource(self);" << endl; + s << INDENT << "PySide::Signal::updateSourceObject(self);" << endl; s << INDENT << "metaObject = cptr->metaObject(); // <- init python qt properties" << endl; s << INDENT << "if (kwds && !PySide::fillQtProperties(self, metaObject, kwds, argNames, " << argNamesSet.count() << "))" << endl; { @@ -3025,14 +3025,14 @@ void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaC return; s << INDENT << "// Initialize signals" << endl; - s << INDENT << "PyObject* signal_item;" << endl << endl; + s << INDENT << "PySideSignal* signal_item;" << endl << endl; foreach(QString funcName, signatures.keys()) { - s << INDENT << "signal_item = PySide::signalNew(\"" << funcName <<"\""; + s << INDENT << "signal_item = PySide::Signal::newObject(\"" << funcName <<"\""; foreach(QString signature, signatures[funcName]) s << ", \"" + signature << "\""; s << ", NULL);" << endl; - s << INDENT << "PySide::addSignalToWrapper(&" + cpythonTypeName(metaClass) + ", \""; + s << INDENT << "PySide::Signal::addSignalToWrapper(&" + cpythonTypeName(metaClass) + ", \""; s << funcName << "\", signal_item);" << endl; s << INDENT << "Py_DECREF(signal_item);" << endl; } @@ -3514,8 +3514,8 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, const AbstractMetaClass s << INDENT << "if (attr && PyObject_TypeCheck(attr, &PySideSignalType)) {" << endl; { Indentation indent(INDENT); - s << INDENT << "PyObject* signal = reinterpret_cast(PySide::signalInitialize(attr, name, self));" << endl - << INDENT << "PyObject_SetAttr(self, name, signal);" << endl + s << INDENT << "PyObject* signal = reinterpret_cast(PySide::Signal::initialize(reinterpret_cast(attr), name, self));" << endl + << INDENT << "PyObject_SetAttr(self, name, reinterpret_cast(signal));" << endl << INDENT << "return signal;" << endl; } s << INDENT << "}" << endl; @@ -3542,9 +3542,8 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, const AbstractMetaClass << INDENT << "if (signalList.size() > 0) {" << endl; { Indentation indent(INDENT); - s << INDENT << "PyObject* pySignal = PySide::signalNewFromMethod(self, signalList);" << endl + s << INDENT << "PyObject* pySignal = reinterpret_cast(PySide::Signal::newObjectFromMethod(self, signalList));" << endl << INDENT << "PyObject_SetAttr(self, name, pySignal);" << endl - << INDENT << "PyObject_GenericSetAttr(self, name, pySignal);" << endl << INDENT << "return pySignal;" << endl; } s << INDENT << "}" << endl; diff --git a/generator/headergenerator.cpp b/generator/headergenerator.cpp index 12d246a1..97cec4b7 100644 --- a/generator/headergenerator.cpp +++ b/generator/headergenerator.cpp @@ -436,7 +436,7 @@ void HeaderGenerator::finishGeneration() s << INDENT << INDENT << "typeName = typeid(*value).name();" << endl; s << INDENT << "PyObject* pyObj = Shiboken::SbkBaseWrapper_New(reinterpret_cast(SbkType<" << metaClass->qualifiedCppName() << " >())," << "value, hasOwnership, isExactType, typeName);" << endl; - s << INDENT << "PySide::signalUpdateSource(pyObj);" << endl; + s << INDENT << "PySide::Signal::updateSourceObject(pyObj);" << endl; s << INDENT << "return pyObj;" << endl; s << '}' << endl; From d77d0948463d31be329c67a4320ab1354219283a Mon Sep 17 00:00:00 2001 From: renatofilho Date: Fri, 29 Oct 2010 18:55:51 -0300 Subject: [PATCH 094/564] Updated code generation to new libpyside files. Reviewer: Marcelo Lira Lauro Neto --- generator/cppgenerator.cpp | 12 ++++++------ generator/headergenerator.cpp | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 428b1848..a44b79c3 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -163,8 +163,8 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl s << "// default includes" << endl; s << "#include " << endl; if (usePySideExtensions()) { - s << "#include " << endl; - s << "#include " << endl; + s << "#include " << endl; + s << "#include " << endl; s << "#include " << endl; } @@ -3454,10 +3454,10 @@ void CppGenerator::writeSetattroFunction(QTextStream& s, const AbstractMetaClass s << "static int " << cpythonSetattroFunctionName(metaClass) << "(PyObject* self, PyObject* name, PyObject* value)" << endl; s << '{' << endl; if (usePySideExtensions()) { - s << INDENT << "Shiboken::AutoDecRef pp(reinterpret_cast(PySide::qpropertyGetObject(self, name)));" << endl; + s << INDENT << "Shiboken::AutoDecRef pp(reinterpret_cast(PySide::Property::getObject(self, name)));" << endl; s << INDENT << "if (!pp.isNull())" << endl; Indentation indent(INDENT); - s << INDENT << "return PySide::qpropertySet(reinterpret_cast(pp.object()), self, value);" << endl; + s << INDENT << "return PySide::Property::setValue(reinterpret_cast(pp.object()), self, value);" << endl; } s << INDENT << "return PyObject_GenericSetAttr(self, name, value);" << endl; s << '}' << endl; @@ -3495,10 +3495,10 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, const AbstractMetaClass } s << INDENT << "PyObject* attr = PyObject_GenericGetAttr(self, name);" << endl; if (usePySideExtensions() && (metaClass->qualifiedCppName() == "QObject")) { - s << INDENT << "if (attr && PySide::isQPropertyType(attr)) {" << endl; + s << INDENT << "if (attr && PySide::Property::isPropertyType(attr)) {" << endl; { Indentation indent(INDENT); - s << INDENT << "PyObject *value = PySide::qpropertyGet(reinterpret_cast(attr), self);" << endl; + s << INDENT << "PyObject *value = PySide::Property::getValue(reinterpret_cast(attr), self);" << endl; s << INDENT << "if (!value)" << endl; { Indentation indentation(INDENT); diff --git a/generator/headergenerator.cpp b/generator/headergenerator.cpp index 97cec4b7..ae9c4941 100644 --- a/generator/headergenerator.cpp +++ b/generator/headergenerator.cpp @@ -386,7 +386,7 @@ void HeaderGenerator::finishGeneration() s << "#include " << endl; s << "#include " << endl << endl; if (usePySideExtensions()) - s << "#include " << endl; + s << "#include " << endl; QStringList requiredTargetImports = TypeDatabase::instance()->requiredTargetImports(); if (!requiredTargetImports.isEmpty()) { From a97ff930b29f6c4d51fdda0f448d172ceb83654e Mon Sep 17 00:00:00 2001 From: renatofilho Date: Thu, 4 Nov 2010 17:37:48 -0300 Subject: [PATCH 095/564] Fixed code generation for functions virtual with know type implementation. Fixes bug #449. Reviewer: Luciano Wolf Hugo Parente Lima --- generator/cppgenerator.cpp | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index a44b79c3..0a1cd315 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2005,25 +2005,41 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f } else { if (func->ownerClass()) { #ifndef AVOID_PROTECTED_HACK - if (!func->isStatic()) + if (func->isStatic()) + mc << func->ownerClass()->qualifiedCppName() << "::"; + else mc << CPP_SELF_VAR "->"; - if (!func->isAbstract()) - mc << "::" << func->ownerClass()->qualifiedCppName() << "::"; + + if (!func->isAbstract() && func->isVirtual()) + mc << "::%CLASS_NAME::"; + mc << func->originalName(); #else - if (!func->isStatic()) { + if (func->isStatic()) + mc << func->ownerClass()->qualifiedCppName() << "::"; + else { if (func->isProtected()) mc << "((" << wrapperName(func->ownerClass()) << "*) "; mc << CPP_SELF_VAR << (func->isProtected() ? ")" : "") << "->"; } - if (!func->isAbstract()) - mc << (func->isProtected() ? wrapperName(func->ownerClass()) : "::" + func->ownerClass()->qualifiedCppName()) << "::"; + if (!func->isAbstract() && func->isVirtual()) + mc << (func->isProtected() ? wrapperName(func->ownerClass()) : "::%CLASS_NAME::"); mc << func->originalName() << (func->isProtected() ? "_protected" : ""); #endif } else { mc << func->originalName(); } mc << '(' << userArgs.join(", ") << ')'; + if (!func->isAbstract() && func->isVirtual()) { + mc.flush(); + QString virtualCall(methodCall); + QString normalCall(methodCall); + + virtualCall = virtualCall.replace("%CLASS_NAME", func->ownerClass()->qualifiedCppName()); + normalCall = normalCall.replace("::%CLASS_NAME::", ""); + methodCall = ""; + mc << "(Shiboken::isUserType(self) ? " << virtualCall << ":" << normalCall << ")"; + } } } From 4120f5e4b8a2781a917d97395b251fbc0bf8c8d8 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Fri, 5 Nov 2010 16:35:59 -0300 Subject: [PATCH 096/564] Implemented support to dynamic slots on generated code. Fixes bug #451. Reviewer: Luciano Wolf Hugo Parente Lima --- generator/cppgenerator.cpp | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 0a1cd315..77c34000 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -168,12 +168,13 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl s << "#include " << endl; } - s << "#include \n"; - s << "#include \n"; + s << "#include " << endl; + s << "#include " << endl; if (usePySideExtensions()) { if (metaClass->isQObject()) { - s << "#include \n"; - s << "#include \n"; + s << "#include " << endl; + s << "#include " << endl; + s << "#include " << endl; } } @@ -3550,9 +3551,30 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, const AbstractMetaClass { Indentation indent(INDENT); s << INDENT << "QMetaMethod method = metaObject->method(i);" << endl - << INDENT << "if ((method.methodType() == QMetaMethod::Signal) &&" << endl - << INDENT << "QString(method.signature()).startsWith(cname))" << endl - << INDENT << "signalList.append(method);" << endl; + << INDENT << "if (QString(method.signature()).startsWith(cname)) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "if (method.methodType() == QMetaMethod::Signal) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "signalList.append(method);" << endl; + } + s << INDENT << "} else {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PySideMetaFunction* func = PySide::MetaFunction::newObject(cppSelf, i);" << endl + << INDENT << "if (func) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "PyObject_SetAttr(self, name, (PyObject*)func);" << endl + << INDENT << "return (PyObject*)func;" << endl; + } + s << INDENT << "}" << endl; + } + s << INDENT << "}" << endl; + } + s << INDENT << "}" << endl; + } s << INDENT << "}" << endl << INDENT << "if (signalList.size() > 0) {" << endl; From 167959faa575856b48c951fd9cc500049004cf60 Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Tue, 9 Nov 2010 10:08:48 -0300 Subject: [PATCH 097/564] Fixed overload decisor sorting to put QStrings after pointers to wrapped objects. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a special extension for Qt bindings. Since QStrings accept None values the same way object and value types accept, to avoid confusion and calling the wrong signature QString must go after object and value pointers. This wasn't a problem before, but now QString is a primitive-type and the decisor has no access to its implicit conversions, and thus can't sort it properly. Reviewed by Luciano Wolf Reviewed by Renato Araújo --- generator/overloaddata.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/generator/overloaddata.cpp b/generator/overloaddata.cpp index 9be972f1..031c0684 100644 --- a/generator/overloaddata.cpp +++ b/generator/overloaddata.cpp @@ -147,6 +147,9 @@ void OverloadData::sortNextOverloads() OverloadSortData sortData; bool checkPyObject = false; int pyobjectIndex = 0; + bool checkQString = false; + bool hasObjectPointer = false; + int qstringIndex = 0; // Primitive types that are not int, long, short, // char and their respective unsigned counterparts. @@ -172,6 +175,15 @@ void OverloadData::sortNextOverloads() if (!checkPyObject && getTypeName(ov->argType()).contains("PyObject")) { checkPyObject = true; pyobjectIndex = sortData.lastProcessedItemId(); + } else if (!checkQString && getTypeName(ov->argType()) == "QString") { + checkQString = true; + qstringIndex = sortData.lastProcessedItemId(); + if (referenceFunction()->name() == "QListWidgetItem") + qDebug() << ov->argType()->minimalSignature() << " checkQString: " << checkQString; + } else if (!hasObjectPointer && (ov->argType()->isValuePointer() || ov->argType()->typeEntry()->isObject() )) { + hasObjectPointer = true; + if (referenceFunction()->name() == "QListWidgetItem") + qDebug() << ov->argType()->minimalSignature() << " hasObjectPointer: " << hasObjectPointer; } foreach (const AbstractMetaType* instantiation, ov->argType()->instantiations()) { @@ -267,6 +279,8 @@ void OverloadData::sortNextOverloads() /* Add dependency on PyObject, so its check is the last one (too generic) */ if (checkPyObject && !targetTypeEntryName.contains("PyObject")) graph.addEdge(sortData.map[targetTypeEntryName], pyobjectIndex); + else if (checkQString && hasObjectPointer && targetTypeEntryName != "QString") + graph.addEdge(sortData.map[targetTypeEntryName], qstringIndex); if (targetTypeEntry->isEnum()) { for (int i = 0; i < numPrimitives; ++i) { From 9bb1956c20892af5379a2fa45b2c1e3af306dd25 Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Tue, 9 Nov 2010 15:38:29 -0300 Subject: [PATCH 098/564] Removed debug statements mistakenly commited. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed by Luciano Wolf Reviewed by Renato Araújo --- generator/overloaddata.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/generator/overloaddata.cpp b/generator/overloaddata.cpp index 031c0684..3ad657ab 100644 --- a/generator/overloaddata.cpp +++ b/generator/overloaddata.cpp @@ -178,12 +178,8 @@ void OverloadData::sortNextOverloads() } else if (!checkQString && getTypeName(ov->argType()) == "QString") { checkQString = true; qstringIndex = sortData.lastProcessedItemId(); - if (referenceFunction()->name() == "QListWidgetItem") - qDebug() << ov->argType()->minimalSignature() << " checkQString: " << checkQString; } else if (!hasObjectPointer && (ov->argType()->isValuePointer() || ov->argType()->typeEntry()->isObject() )) { hasObjectPointer = true; - if (referenceFunction()->name() == "QListWidgetItem") - qDebug() << ov->argType()->minimalSignature() << " hasObjectPointer: " << hasObjectPointer; } foreach (const AbstractMetaType* instantiation, ov->argType()->instantiations()) { From 9c6fb1d821065e61f85a59503dea63f4e7b49180 Mon Sep 17 00:00:00 2001 From: renatofilho Date: Tue, 9 Nov 2010 16:09:01 -0300 Subject: [PATCH 099/564] Fixed overload functions with QVariant. Decrease the QVariant priority during the function overload. Reviewer: Luciano Wolf Marcelo Lira --- generator/overloaddata.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/generator/overloaddata.cpp b/generator/overloaddata.cpp index 3ad657ab..ca0babc7 100644 --- a/generator/overloaddata.cpp +++ b/generator/overloaddata.cpp @@ -148,8 +148,10 @@ void OverloadData::sortNextOverloads() bool checkPyObject = false; int pyobjectIndex = 0; bool checkQString = false; - bool hasObjectPointer = false; int qstringIndex = 0; + bool checkQVariant = false; + int qvariantIndex = 0; + bool hasObjectPointer = false; // Primitive types that are not int, long, short, // char and their respective unsigned counterparts. @@ -175,6 +177,9 @@ void OverloadData::sortNextOverloads() if (!checkPyObject && getTypeName(ov->argType()).contains("PyObject")) { checkPyObject = true; pyobjectIndex = sortData.lastProcessedItemId(); + } else if (!checkQVariant && getTypeName(ov->argType()) == "QVariant") { + checkQVariant = true; + qvariantIndex = sortData.lastProcessedItemId(); } else if (!checkQString && getTypeName(ov->argType()) == "QString") { checkQString = true; qstringIndex = sortData.lastProcessedItemId(); @@ -275,6 +280,8 @@ void OverloadData::sortNextOverloads() /* Add dependency on PyObject, so its check is the last one (too generic) */ if (checkPyObject && !targetTypeEntryName.contains("PyObject")) graph.addEdge(sortData.map[targetTypeEntryName], pyobjectIndex); + else if (checkQVariant && targetTypeEntryName != "QVariant") + graph.addEdge(sortData.map[targetTypeEntryName], qvariantIndex); else if (checkQString && hasObjectPointer && targetTypeEntryName != "QString") graph.addEdge(sortData.map[targetTypeEntryName], qstringIndex); From d8e2d87f8962175f90fea01026e0a6099ad7f93c Mon Sep 17 00:00:00 2001 From: renatofilho Date: Wed, 10 Nov 2010 12:49:49 -0300 Subject: [PATCH 100/564] Revert "Fixed overload decisor sorting to put QStrings after pointers to wrapped objects." This reverts commit 167959faa575856b48c951fd9cc500049004cf60. Conflicts: generator/overloaddata.cpp --- generator/overloaddata.cpp | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/generator/overloaddata.cpp b/generator/overloaddata.cpp index ca0babc7..9be972f1 100644 --- a/generator/overloaddata.cpp +++ b/generator/overloaddata.cpp @@ -147,11 +147,6 @@ void OverloadData::sortNextOverloads() OverloadSortData sortData; bool checkPyObject = false; int pyobjectIndex = 0; - bool checkQString = false; - int qstringIndex = 0; - bool checkQVariant = false; - int qvariantIndex = 0; - bool hasObjectPointer = false; // Primitive types that are not int, long, short, // char and their respective unsigned counterparts. @@ -177,14 +172,6 @@ void OverloadData::sortNextOverloads() if (!checkPyObject && getTypeName(ov->argType()).contains("PyObject")) { checkPyObject = true; pyobjectIndex = sortData.lastProcessedItemId(); - } else if (!checkQVariant && getTypeName(ov->argType()) == "QVariant") { - checkQVariant = true; - qvariantIndex = sortData.lastProcessedItemId(); - } else if (!checkQString && getTypeName(ov->argType()) == "QString") { - checkQString = true; - qstringIndex = sortData.lastProcessedItemId(); - } else if (!hasObjectPointer && (ov->argType()->isValuePointer() || ov->argType()->typeEntry()->isObject() )) { - hasObjectPointer = true; } foreach (const AbstractMetaType* instantiation, ov->argType()->instantiations()) { @@ -280,10 +267,6 @@ void OverloadData::sortNextOverloads() /* Add dependency on PyObject, so its check is the last one (too generic) */ if (checkPyObject && !targetTypeEntryName.contains("PyObject")) graph.addEdge(sortData.map[targetTypeEntryName], pyobjectIndex); - else if (checkQVariant && targetTypeEntryName != "QVariant") - graph.addEdge(sortData.map[targetTypeEntryName], qvariantIndex); - else if (checkQString && hasObjectPointer && targetTypeEntryName != "QString") - graph.addEdge(sortData.map[targetTypeEntryName], qstringIndex); if (targetTypeEntry->isEnum()) { for (int i = 0; i < numPrimitives; ++i) { From 4a21523d46b4aa09d2435e351b0dfb1c95dcee05 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 5 Nov 2010 14:02:45 -0200 Subject: [PATCH 101/564] Remove unused variables. --- generator/shibokengenerator.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/generator/shibokengenerator.cpp b/generator/shibokengenerator.cpp index ee4ccd33..67f5fca8 100644 --- a/generator/shibokengenerator.cpp +++ b/generator/shibokengenerator.cpp @@ -516,7 +516,6 @@ void ShibokenGenerator::writeToPythonConversion(QTextStream& s, const AbstractMe return; // exclude const on Objects - const TypeEntry* typeEntry = type->typeEntry(); Options flags = getConverterOptions(type); writeBaseConversion(s, type, context, flags); s << "toPython"; @@ -793,7 +792,6 @@ QString ShibokenGenerator::cpythonCheckFunction(const AbstractMetaType* metaType QString str; QTextStream s(&str); // exclude const on Objects - const TypeEntry* typeEntry = metaType->typeEntry(); Options flags = getConverterOptions(metaType); writeBaseConversion(s, metaType, 0, flags); s.flush(); From 1f96f42eb019097ec4f145adce6a4fe342171530 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 10 Nov 2010 15:29:56 -0200 Subject: [PATCH 102/564] Bump version to 1.0.0 --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f2c29a64..9fd6ff32 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,9 +14,9 @@ find_package(PythonInterpWithDebug) add_definitions(${QT_DEFINITIONS}) -set(shiboken_MAJOR_VERSION "0") -set(shiboken_MINOR_VERSION "5") -set(shiboken_MICRO_VERSION "2") +set(shiboken_MAJOR_VERSION "1") +set(shiboken_MINOR_VERSION "0") +set(shiboken_MICRO_VERSION "0") set(shiboken_VERSION "${shiboken_MAJOR_VERSION}.${shiboken_MINOR_VERSION}.${shiboken_MICRO_VERSION}") option(AVOID_PROTECTED_HACK "Avoid protected hack on generated bindings." FALSE) From 95bc879ad706a47c965b2a62dd5b758cbd796b3d Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 5 Nov 2010 14:18:54 -0200 Subject: [PATCH 103/564] pyenum.{h|cpp} moved to sbkenum.{h|cpp} --- generator/headergenerator.cpp | 2 +- libshiboken/CMakeLists.txt | 4 ++-- libshiboken/basewrapper.cpp | 2 +- libshiboken/conversions.h | 2 +- libshiboken/{pyenum.cpp => sbkenum.cpp} | 4 ++-- libshiboken/{pyenum.h => sbkenum.h} | 6 +++--- libshiboken/shiboken.h | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) rename libshiboken/{pyenum.cpp => sbkenum.cpp} (97%) rename libshiboken/{pyenum.h => sbkenum.h} (94%) diff --git a/generator/headergenerator.cpp b/generator/headergenerator.cpp index ae9c4941..5a9721c9 100644 --- a/generator/headergenerator.cpp +++ b/generator/headergenerator.cpp @@ -381,7 +381,7 @@ void HeaderGenerator::finishGeneration() s << "#include " << endl; s << "#include " << endl; - s << "#include " << endl; + s << "#include " << endl; s << "#include " << endl; s << "#include " << endl; s << "#include " << endl << endl; diff --git a/libshiboken/CMakeLists.txt b/libshiboken/CMakeLists.txt index f21681f5..a329eec0 100644 --- a/libshiboken/CMakeLists.txt +++ b/libshiboken/CMakeLists.txt @@ -26,7 +26,7 @@ set(libshiboken_SRC basewrapper.cpp gilstate.cpp helper.cpp -pyenum.cpp +sbkenum.cpp bindingmanager.cpp threadstatesaver.cpp typeresolver.cpp @@ -49,7 +49,7 @@ install(FILES conversions.h gilstate.h helper.h - pyenum.h + sbkenum.h python25compat.h sbkdbg.h shiboken.h diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 4983f678..ae5b6dda 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -22,7 +22,7 @@ #include "basewrapper.h" #include "basewrapper_p.h" -#include "pyenum.h" +#include "sbkenum.h" #include #include #include "autodecref.h" diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index 475902ea..d4059b56 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -28,7 +28,7 @@ #include #include -#include "pyenum.h" +#include "sbkenum.h" #include "basewrapper.h" #include "bindingmanager.h" #include "sbkdbg.h" diff --git a/libshiboken/pyenum.cpp b/libshiboken/sbkenum.cpp similarity index 97% rename from libshiboken/pyenum.cpp rename to libshiboken/sbkenum.cpp index 6295c915..f71a7476 100644 --- a/libshiboken/pyenum.cpp +++ b/libshiboken/sbkenum.cpp @@ -1,7 +1,7 @@ /* * This file is part of the Shiboken Python Bindings Generator project. * - * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * @@ -20,7 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "pyenum.h" +#include "sbkenum.h" namespace Shiboken { diff --git a/libshiboken/pyenum.h b/libshiboken/sbkenum.h similarity index 94% rename from libshiboken/pyenum.h rename to libshiboken/sbkenum.h index 9c902652..447997e7 100644 --- a/libshiboken/pyenum.h +++ b/libshiboken/sbkenum.h @@ -1,7 +1,7 @@ /* * This file is part of the Shiboken Python Bindings Generator project. * - * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * @@ -20,8 +20,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef SBK_PYENUM_H -#define SBK_PYENUM_H +#ifndef SBKENUM_H +#define SBKENUM_H #include #include "shibokenmacros.h" diff --git a/libshiboken/shiboken.h b/libshiboken/shiboken.h index 83c27b2c..6a2df306 100644 --- a/libshiboken/shiboken.h +++ b/libshiboken/shiboken.h @@ -31,7 +31,7 @@ #include "gilstate.h" #include "threadstatesaver.h" #include "helper.h" -#include "pyenum.h" +#include "sbkenum.h" #include "shibokenmacros.h" #include "typeresolver.h" From d5630195312a4eb107cb6f48aae54038a9ca4681 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Mon, 8 Nov 2010 17:04:58 -0200 Subject: [PATCH 104/564] Create enum python types on the fly, avoiding generation of structs and duplication of many C functions. --- generator/cppgenerator.cpp | 133 ++++++--------------------------- generator/cppgenerator.h | 2 - libshiboken/conversions.h | 6 +- libshiboken/sbkenum.cpp | 149 +++++++++++++++++++++++++++---------- libshiboken/sbkenum.h | 27 +++---- 5 files changed, 144 insertions(+), 173 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 77c34000..e7f0e428 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -431,8 +431,6 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl s << endl; } - writeEnumDefinition(s, cppEnum); - if (hasFlags) { // Write Enum as Flags definition (at the moment used only by QFlags) writeFlagsDefinition(s, cppEnum); @@ -2927,13 +2925,18 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu s << cppEnum->name() << endl; if (!cppEnum->isAnonymous()) { - s << INDENT << cpythonTypeNameExt(cppEnum->typeEntry()) << " = &" << cpythonTypeName(cppEnum->typeEntry()) << ';' << endl; - s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << cpythonName << "_Type) < 0)" << endl; + s << INDENT << "PyTypeObject* " << cpythonName << " = Shiboken::Enum::newType(\"" << cppEnum->name() << "\");" << endl; + + if (cppEnum->typeEntry()->flags()) + s << INDENT << cpythonName << "->tp_as_number = &" << cpythonName << "_as_number;" << endl; + + s << INDENT << cpythonTypeNameExt(cppEnum->typeEntry()) << " = " << cpythonName << ';' << endl; + s << INDENT << "if (PyType_Ready(" << cpythonName << ") < 0)" << endl; s << INDENT << INDENT << "return;" << endl; s << INDENT << addFunction << endl; s << INDENT << INDENT << INDENT << '\"' << cppEnum->name() << "\","; - s << "((PyObject*)&" << cpythonName << "_Type));" << endl << endl; + s << "((PyObject*)" << cpythonName << "));" << endl << endl; FlagsTypeEntry* flags = cppEnum->typeEntry()->flags(); if (flags) { @@ -2970,13 +2973,12 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu #endif bool shouldDecrefNumber = false; - QString enumItemText = "enum_item"; + QString enumItemText = "enumItem"; if (!cppEnum->isAnonymous()) { - s << INDENT << "enum_item = Shiboken::SbkEnumObject_New(&"; - s << cpythonName << "_Type," << enumValueText << ", \""; - s << enumValue->name() << "\");" << endl; + s << INDENT << "enumItem = Shiboken::Enum::newItem(" << cpythonName << "," << enumValueText; + s << ", \"" << enumValue->name() << "\");" << endl; } else if (cppEnum->enclosingClass()) { - s << INDENT << "enum_item = PyInt_FromLong(" << enumValueText << ");" << endl; + s << INDENT << "enumItem = PyInt_FromLong(" << enumValueText << ");" << endl; shouldDecrefNumber = true; } else { enumItemText = enumValueText; @@ -2984,13 +2986,13 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu s << INDENT << addFunction << '"' << enumValue->name() << "\", " << enumItemText << ");" << endl; if (shouldDecrefNumber) - s << INDENT << "Py_DECREF(enum_item);" << endl; + s << INDENT << "Py_DECREF(enumItem);" << endl; if (!cppEnum->isAnonymous()) { - s << INDENT << "Py_DECREF(enum_item);" << endl; - s << INDENT << "PyDict_SetItemString(" << cpythonName << "_Type.tp_dict,"; - s << '"' << enumValue->name() << "\", enum_item);" << endl; - s << INDENT << "Py_DECREF(enum_item);" << endl; + s << INDENT << "Py_DECREF(enumItem);" << endl; + s << INDENT << "PyDict_SetItemString(" << cpythonName << "->tp_dict,"; + s << '"' << enumValue->name() << "\", enumItem);" << endl; + s << INDENT << "Py_DECREF(enumItem);" << endl; } } @@ -3003,7 +3005,7 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu } - s << endl; + s << INDENT << "// end of enum " << cppEnum->name() << endl << endl; } void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaClass* metaClass) @@ -3056,98 +3058,6 @@ void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaC s << endl; } -void CppGenerator::writeEnumNewMethod(QTextStream& s, const AbstractMetaEnum* cppEnum) -{ - QString cpythonName = cpythonEnumName(cppEnum); - s << "static PyObject* "; - s << cpythonName << "_New(PyTypeObject* type, PyObject* args, PyObject* kwds)" << endl; - s << '{' << endl; - s << INDENT << "int item_value = 0;" << endl; - s << INDENT << "if (!PyArg_ParseTuple(args, \"|i:__new__\", &item_value))" << endl; - { - Indentation indent(INDENT); - s << INDENT << "return 0;" << endl; - } - s << INDENT << "PyObject* self = Shiboken::SbkEnumObject_New(type, item_value);" << endl << endl; - s << INDENT << "if (!self)" << endl; - { - Indentation indent(INDENT); - s << INDENT << "return 0;" << endl; - } - s << INDENT << "return self;" << endl << '}' << endl; -} - -void CppGenerator::writeEnumDefinition(QTextStream& s, const AbstractMetaEnum* cppEnum) -{ - QString cpythonName = cpythonEnumName(cppEnum); - QString tp_as_number("0"); - if (cppEnum->typeEntry()->flags()) - tp_as_number = QString("&%1_as_number").arg(cpythonName); - - - s << "static PyGetSetDef " << cpythonName << "_getsetlist[] = {" << endl; - s << INDENT << "{const_cast(\"name\"), (getter)Shiboken::SbkEnumObject_name}," << endl; - s << INDENT << "{0} // Sentinel" << endl; - s << "};" << endl << endl; - - QString newFunc = cpythonName + "_New"; - - s << "// forward declaration of new function" << endl; - s << "static PyObject* " << newFunc << "(PyTypeObject*, PyObject*, PyObject*);" << endl << endl; - - s << "static PyTypeObject " << cpythonName << "_Type = {" << endl; - s << INDENT << "PyObject_HEAD_INIT(&Shiboken::SbkEnumType_Type)" << endl; - s << INDENT << "/*ob_size*/ 0," << endl; - s << INDENT << "/*tp_name*/ \"" << cppEnum->name() << "\"," << endl; - s << INDENT << "/*tp_basicsize*/ sizeof(Shiboken::SbkEnumObject)," << endl; - s << INDENT << "/*tp_itemsize*/ 0," << endl; - s << INDENT << "/*tp_dealloc*/ 0," << endl; - s << INDENT << "/*tp_print*/ 0," << endl; - s << INDENT << "/*tp_getattr*/ 0," << endl; - s << INDENT << "/*tp_setattr*/ 0," << endl; - s << INDENT << "/*tp_compare*/ 0," << endl; - s << INDENT << "/*tp_repr*/ Shiboken::SbkEnumObject_repr," << endl; - s << INDENT << "/*tp_as_number*/ " << tp_as_number << ',' << endl; - s << INDENT << "/*tp_as_sequence*/ 0," << endl; - s << INDENT << "/*tp_as_mapping*/ 0," << endl; - s << INDENT << "/*tp_hash*/ 0," << endl; - s << INDENT << "/*tp_call*/ 0," << endl; - s << INDENT << "/*tp_str*/ Shiboken::SbkEnumObject_repr," << endl; - s << INDENT << "/*tp_getattro*/ 0," << endl; - s << INDENT << "/*tp_setattro*/ 0," << endl; - s << INDENT << "/*tp_as_buffer*/ 0," << endl; - s << INDENT << "/*tp_flags*/ Py_TPFLAGS_DEFAULT," << endl; - s << INDENT << "/*tp_doc*/ 0," << endl; - s << INDENT << "/*tp_traverse*/ 0," << endl; - s << INDENT << "/*tp_clear*/ 0," << endl; - s << INDENT << "/*tp_richcompare*/ 0," << endl; - s << INDENT << "/*tp_weaklistoffset*/ 0," << endl; - s << INDENT << "/*tp_iter*/ 0," << endl; - s << INDENT << "/*tp_iternext*/ 0," << endl; - s << INDENT << "/*tp_methods*/ 0," << endl; - s << INDENT << "/*tp_members*/ 0," << endl; - s << INDENT << "/*tp_getset*/ " << cpythonName << "_getsetlist," << endl; - s << INDENT << "/*tp_base*/ &PyInt_Type," << endl; - s << INDENT << "/*tp_dict*/ 0," << endl; - s << INDENT << "/*tp_descr_get*/ 0," << endl; - s << INDENT << "/*tp_descr_set*/ 0," << endl; - s << INDENT << "/*tp_dictoffset*/ 0," << endl; - s << INDENT << "/*tp_init*/ 0," << endl; - s << INDENT << "/*tp_alloc*/ 0," << endl; - s << INDENT << "/*tp_new*/ " << newFunc << ',' << endl; - s << INDENT << "/*tp_free*/ 0," << endl; - s << INDENT << "/*tp_is_gc*/ 0," << endl; - s << INDENT << "/*tp_bases*/ 0," << endl; - s << INDENT << "/*tp_mro*/ 0," << endl; - s << INDENT << "/*tp_cache*/ 0," << endl; - s << INDENT << "/*tp_subclasses*/ 0," << endl; - s << INDENT << "/*tp_weaklist*/ 0" << endl; - s << "};" << endl << endl; - - writeEnumNewMethod(s, cppEnum); - s << endl; -} - void CppGenerator::writeFlagsMethods(QTextStream& s, const AbstractMetaEnum* cppEnum) { writeFlagsBinaryOperator(s, cppEnum, "and", "&"); @@ -3226,7 +3136,7 @@ void CppGenerator::writeFlagsDefinition(QTextStream& s, const AbstractMetaEnum* s << INDENT << "/*tp_setattr*/ 0," << endl; s << INDENT << "/*tp_compare*/ 0," << endl; s << INDENT << "/*tp_repr*/ 0," << endl; - s << INDENT << "/*tp_as_number*/ " << enumName << "_Type.tp_as_number," << endl; + s << INDENT << "/*tp_as_number*/ &" << enumName << "_as_number," << endl; s << INDENT << "/*tp_as_sequence*/ 0," << endl; s << INDENT << "/*tp_as_mapping*/ 0," << endl; s << INDENT << "/*tp_hash*/ 0," << endl; @@ -3368,7 +3278,7 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m if (!metaClass->enums().isEmpty()) { s << INDENT << "// Initialize enums" << endl; - s << INDENT << "PyObject* enum_item;" << endl << endl; + s << INDENT << "PyObject* enumItem;" << endl << endl; } foreach (const AbstractMetaEnum* cppEnum, metaClass->enums()) { @@ -3703,7 +3613,6 @@ void CppGenerator::finishGeneration() foreach (const AbstractMetaEnum* cppEnum, globalEnums()) { if (cppEnum->isAnonymous() || cppEnum->isPrivate()) continue; - writeEnumDefinition(s, cppEnum); s << endl; } @@ -3781,7 +3690,7 @@ void CppGenerator::finishGeneration() if (!globalEnums().isEmpty()) { s << INDENT << "// Initialize enums" << endl; - s << INDENT << "PyObject* enum_item;" << endl << endl; + s << INDENT << "PyObject* enumItem;" << endl << endl; } foreach (const AbstractMetaEnum* cppEnum, globalEnums()) { diff --git a/generator/cppgenerator.h b/generator/cppgenerator.h index 645f63fd..4374eb5e 100644 --- a/generator/cppgenerator.h +++ b/generator/cppgenerator.h @@ -145,8 +145,6 @@ class CppGenerator : public ShibokenGenerator void writeRichCompareFunction(QTextStream& s, const AbstractMetaClass* metaClass); void writeToPythonFunction(QTextStream& s, const AbstractMetaClass* metaClass); - void writeEnumNewMethod(QTextStream& s, const AbstractMetaEnum* cppEnum); - void writeEnumDefinition(QTextStream& s, const AbstractMetaEnum* metaEnum); void writeEnumInitialization(QTextStream& s, const AbstractMetaEnum* metaEnum); void writeSignalInitialization(QTextStream& s, const AbstractMetaClass* metaClass); diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index d4059b56..67e62792 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -491,11 +491,11 @@ struct EnumConverter static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } static inline PyObject* toPython(CppEnum cppenum) { - return SbkEnumObject_New(SbkType(), (long) cppenum); + return Shiboken::Enum::newItem(Shiboken::SbkType(), (long) cppenum); } - static inline CppEnum toCpp(PyObject* pyobj) + static inline CppEnum toCpp(PyObject* pyObj) { - return (CppEnum) reinterpret_cast(pyobj)->ob_ival; + return (CppEnum) Shiboken::Enum::getValue(pyObj);; } }; diff --git a/libshiboken/sbkenum.cpp b/libshiboken/sbkenum.cpp index f71a7476..34a4b772 100644 --- a/libshiboken/sbkenum.cpp +++ b/libshiboken/sbkenum.cpp @@ -21,12 +21,52 @@ */ #include "sbkenum.h" +#include +#include +#include "sbkdbg.h" +#include "autodecref.h" -namespace Shiboken +extern "C" { -extern "C" +struct SbkEnumObject +{ + PyObject_HEAD + long ob_ival; + PyObject* ob_name; +}; + +static PyObject* SbkEnumObject_repr(PyObject* self) +{ + return PyString_FromFormat("", + self->ob_type->tp_name, + PyString_AS_STRING(((SbkEnumObject*)self)->ob_name), + ((SbkEnumObject*)self)->ob_ival); +} + +static PyObject* SbkEnumObject_name(PyObject* self, void*) { + Py_INCREF(((SbkEnumObject*)self)->ob_name); + return ((SbkEnumObject*)self)->ob_name; +} + +static PyObject* SbkEnum_tp_new(PyTypeObject* type, PyObject* args, PyObject* kwds) +{ + int itemValue = 0; + if (!PyArg_ParseTuple(args, "|i:__new__", &itemValue)) + return 0; + + SbkEnumObject* self = PyObject_New(SbkEnumObject, type); + if (!self) + return 0; + self->ob_ival = itemValue; + return reinterpret_cast(self); +} + +static PyGetSetDef SbkEnumGetSetList[] = { + {const_cast("name"), &SbkEnumObject_name}, + {0} // Sentinel +}; PyTypeObject SbkEnumType_Type = { PyObject_HEAD_INIT(0) @@ -77,65 +117,98 @@ PyTypeObject SbkEnumType_Type = { /*tp_weaklist*/ 0 }; -} +} // extern "C" + +namespace Shiboken { -PyObject* -SbkEnumObject_New(PyTypeObject *type, long item_value, PyObject* item_name) +class DeclaredEnumTypes { - if (!item_name) - item_name = PyString_FromString(""); - SbkEnumObject* enum_obj = PyObject_New(SbkEnumObject, type); - enum_obj->ob_name = item_name; - enum_obj->ob_ival = item_value; - return (PyObject*) enum_obj; -} +public: + DeclaredEnumTypes(); + ~DeclaredEnumTypes(); + static DeclaredEnumTypes& instance(); + void addEnumType(PyTypeObject* type); +private: + DeclaredEnumTypes(const DeclaredEnumTypes&); + DeclaredEnumTypes& operator=(const DeclaredEnumTypes&); + std::list m_enumTypes; +}; + +namespace Enum { -PyObject* -SbkEnumObject_New(PyTypeObject *type, long item_value, const char* item_name) +PyObject* newItem(PyTypeObject* enumType, long itemValue, const char* itemName) { - PyObject* py_item_name = 0; - if (item_name) - py_item_name = PyString_FromString(item_name); + if (!itemName) + itemName = ""; + PyObject* pyItemName = PyString_FromString(itemName); - PyObject* enum_obj = SbkEnumObject_New(type, item_value, py_item_name); - if (!enum_obj) { - Py_XDECREF(py_item_name); + SbkEnumObject* enumObj = PyObject_New(SbkEnumObject, enumType); + if (!enumObj) { + Py_XDECREF(pyItemName); return 0; } - if (item_name) { - PyObject* values = PyDict_GetItemString(type->tp_dict, const_cast("values")); + enumObj->ob_name = pyItemName; + enumObj->ob_ival = itemValue; + if (itemName) { + PyObject* values = PyDict_GetItemString(enumType->tp_dict, const_cast("values")); if (!values) { values = PyDict_New(); - PyDict_SetItemString(type->tp_dict, const_cast("values"), values); + PyDict_SetItemString(enumType->tp_dict, const_cast("values"), values); Py_DECREF(values); // ^ values still alive, because setitemstring incref it } - PyDict_SetItemString(values, item_name, enum_obj); + PyDict_SetItemString(values, itemName, reinterpret_cast(enumObj)); } - return enum_obj; + return reinterpret_cast(enumObj); } -extern "C" +PyTypeObject* newType(const char* name) { + PyTypeObject* type = new PyTypeObject; + ::memset(type, 0, sizeof(PyTypeObject)); + type->ob_type = &SbkEnumType_Type; + type->tp_basicsize = sizeof(SbkEnumObject); + type->tp_repr = &SbkEnumObject_repr; + type->tp_str = &SbkEnumObject_repr; + type->tp_flags = Py_TPFLAGS_DEFAULT; + type->tp_base = &PyInt_Type; + type->tp_name = name; + type->tp_getset = SbkEnumGetSetList; + type->tp_new = SbkEnum_tp_new; + + DeclaredEnumTypes::instance().addEnumType(type); + return type; +} -PyObject* -SbkEnumObject_repr(PyObject* self) +long int getValue(PyObject* enumItem) { - return PyString_FromFormat("", - self->ob_type->tp_name, - PyString_AS_STRING(((SbkEnumObject*)self)->ob_name), - ((SbkEnumObject*)self)->ob_ival); + return reinterpret_cast(enumItem)->ob_ival; } -PyObject* -SbkEnumObject_name(PyObject* self) +} // namespace Enum + +DeclaredEnumTypes& DeclaredEnumTypes::instance() { - Py_INCREF(((SbkEnumObject*)self)->ob_name); - return ((SbkEnumObject*)self)->ob_name; + static DeclaredEnumTypes me; + return me; } -} // extern "C" +DeclaredEnumTypes::DeclaredEnumTypes() +{ +} -} // namespace Shiboken +DeclaredEnumTypes::~DeclaredEnumTypes() +{ + std::list::const_iterator it = m_enumTypes.begin(); + for (; it != m_enumTypes.end(); ++it) + delete *it; + m_enumTypes.clear(); +} +void DeclaredEnumTypes::addEnumType(PyTypeObject* type) +{ + m_enumTypes.push_back(type); +} + +} diff --git a/libshiboken/sbkenum.h b/libshiboken/sbkenum.h index 447997e7..50ac9220 100644 --- a/libshiboken/sbkenum.h +++ b/libshiboken/sbkenum.h @@ -26,36 +26,27 @@ #include #include "shibokenmacros.h" -namespace Shiboken -{ - extern "C" { -typedef struct { - PyObject_HEAD - long ob_ival; - PyObject* ob_name; -} SbkEnumObject; - extern LIBSHIBOKEN_API PyTypeObject SbkEnumType_Type; -LIBSHIBOKEN_API PyObject* SbkEnumObject_repr(PyObject* self); -LIBSHIBOKEN_API PyObject* SbkEnumObject_name(PyObject* self); - } // extern "C" +namespace Shiboken +{ + inline bool isShibokenEnum(PyObject* pyObj) { return pyObj->ob_type->ob_type == &SbkEnumType_Type; } -LIBSHIBOKEN_API PyObject* SbkEnumObject_New(PyTypeObject *instanceType, - long item_value, - const char* item_name); -LIBSHIBOKEN_API PyObject* SbkEnumObject_New(PyTypeObject *instanceType, - long item_value, - PyObject* item_name = 0); +namespace Enum +{ + LIBSHIBOKEN_API PyObject* newItem(PyTypeObject* enumType, long itemValue, const char* itemName = 0); + LIBSHIBOKEN_API PyTypeObject* newType(const char* name); + LIBSHIBOKEN_API long getValue(PyObject* enumItem); +} } // namespace Shiboken From 47006421772b9183d8a6a0fd84ff73f5c35b3f07 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 9 Nov 2010 11:07:12 -0200 Subject: [PATCH 105/564] Removed deprecated function: PySequenceToArgcArgv --- libshiboken/helper.cpp | 9 +-------- libshiboken/helper.h | 5 ----- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/libshiboken/helper.cpp b/libshiboken/helper.cpp index c37c5432..297c2b48 100644 --- a/libshiboken/helper.cpp +++ b/libshiboken/helper.cpp @@ -25,14 +25,7 @@ namespace Shiboken { -bool -PySequenceToArgcArgv(PyObject* argList, int* argc, char*** argv, const char* defaultAppName) -{ - return sequenceToArgcArgv(argList, argc, argv, defaultAppName); -} - -bool -sequenceToArgcArgv(PyObject* argList, int* argc, char*** argv, const char* defaultAppName) +bool sequenceToArgcArgv(PyObject* argList, int* argc, char*** argv, const char* defaultAppName) { if (!PySequence_Check(argList)) return false; diff --git a/libshiboken/helper.h b/libshiboken/helper.h index a0630412..9aa06ffe 100644 --- a/libshiboken/helper.h +++ b/libshiboken/helper.h @@ -78,11 +78,6 @@ inline PyObject* makeTuple(const A& a, const B& b, const C& c, const D& d, const */ LIBSHIBOKEN_API bool sequenceToArgcArgv(PyObject* argList, int* argc, char*** argv, const char* defaultAppName = 0); -/** - * \deprecated Use sequenceToArgcArgv instead. - */ -LIBSHIBOKEN_API bool PySequenceToArgcArgv(PyObject* argList, int* argc, char*** argv, const char* defaultAppName = 0); - /** * Convert a python sequence into a heap-allocated array of ints. * From c948d05782056d9b12ab0ccf04fa4e1b30478296 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 9 Nov 2010 11:08:59 -0200 Subject: [PATCH 106/564] Refactor on sequenceToIntArray. --- libshiboken/helper.cpp | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/libshiboken/helper.cpp b/libshiboken/helper.cpp index 297c2b48..50bf6941 100644 --- a/libshiboken/helper.cpp +++ b/libshiboken/helper.cpp @@ -63,41 +63,30 @@ bool sequenceToArgcArgv(PyObject* argList, int* argc, char*** argv, const char* return true; } -int* -sequenceToIntArray(PyObject* obj, bool zeroTerminated) +int* sequenceToIntArray(PyObject* obj, bool zeroTerminated) { - int* array = NULL; - int i; - int size; + AutoDecRef seq(PySequence_Fast(obj, "Sequence of ints expected")); + if (seq.isNull()) + return 0; - if (!PySequence_Check(obj)) { - PyErr_SetString(PyExc_TypeError, "Sequence of ints expected"); - return NULL; - } - - size = PySequence_Size(obj); + Py_ssize_t size = PySequence_Fast_GET_SIZE(seq.object()); + int* array = new int[size + (zeroTerminated ? 1 : 0)]; - array = new int[size + (zeroTerminated ? 1 : 0)]; - - for (i = 0; i < size; i++) { - PyObject* item = PySequence_GetItem(obj, i); + for (int i = 0; i < size; i++) { + PyObject* item = PySequence_Fast_GET_ITEM(seq.object(), i); if (!PyInt_Check(item)) { PyErr_SetString(PyExc_TypeError, "Sequence of ints expected"); - Py_DECREF(item); - if (array) - delete[] array; - return NULL; + delete[] array; + return 0; } else { array[i] = PyInt_AsLong(item); - Py_DECREF(item); } } if (zeroTerminated) - array[i] = 0; + array[size] = 0; return array; } - } // namespace Shiboken From 6280785f538dc033e85826bf2525848c75327ea8 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 9 Nov 2010 16:47:12 -0200 Subject: [PATCH 107/564] Moved Shiboken::SbkBaseWrapper outside Shiboken namespace and added a d-pointer to it. --- generator/cppgenerator.cpp | 12 ++-- libshiboken/basewrapper.cpp | 123 ++++++++++++++++++++------------- libshiboken/basewrapper.h | 66 ++++++++---------- libshiboken/basewrapper_p.h | 77 +++++++++++++++------ libshiboken/bindingmanager.cpp | 24 +++---- libshiboken/bindingmanager.h | 5 +- libshiboken/conversions.h | 4 +- 7 files changed, 182 insertions(+), 129 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index e7f0e428..fe623953 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -779,13 +779,13 @@ void CppGenerator::writeMetaObjectMethod(QTextStream& s, const AbstractMetaClass { Indentation indentation(INDENT); s << INDENT << "PyObject *pySelf = BindingManager::instance().retrieveWrapper(this);\n" - << INDENT << "void *typeData = Shiboken::getTypeUserData(reinterpret_cast(pySelf));" << endl + << INDENT << "void *typeData = Shiboken::getTypeUserData(reinterpret_cast(pySelf));" << endl << INDENT << "if (!typeData) {" << endl; { Indentation indentation2(INDENT); s << INDENT << "m_metaObject = PySide::DynamicQMetaObject::createBasedOn(pySelf, pySelf->ob_type, &" << metaClass->qualifiedCppName() << "::staticMetaObject);" << endl - << INDENT << "Shiboken::setTypeUserData(reinterpret_cast(pySelf), m_metaObject, PySide::deleteDynamicQMetaObject);" << endl; + << INDENT << "Shiboken::setTypeUserData(reinterpret_cast(pySelf), m_metaObject, PySide::deleteDynamicQMetaObject);" << endl; } s << INDENT << "} else {" << endl; { @@ -927,13 +927,13 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun s << endl; } - s << INDENT << "sbkSelf->validCppObject = 1;" << endl; + s << INDENT << "Shiboken::Wrapper::setValidCpp(sbkSelf, true);" << endl; // If the created C++ object has a C++ wrapper the ownership is assigned to Python // (first "1") and the flag indicating that the Python wrapper holds an C++ wrapper // is marked as true (the second "1"). Otherwise the default values apply: // Python owns it and C++ wrapper is false. if (shouldGenerateCppWrapper(overloads.first()->ownerClass())) - s << INDENT << "sbkSelf->containsCppWrapper = 1;" << endl; + s << INDENT << "Shiboken::Wrapper::setHasCppWrapper(sbkSelf, true);" << endl; s << INDENT << "BindingManager::instance().registerWrapper(sbkSelf, cptr);" << endl; // Create metaObject and register signal/slot @@ -1843,7 +1843,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f } if (func->isAbstract()) { - s << INDENT << "if (SbkBaseWrapper_containsCppWrapper(self)) {\n"; + s << INDENT << "if (Shiboken::Wrapper::hasCppWrapper(reinterpret_cast(self))) {\n"; { Indentation indent(INDENT); s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '"; @@ -2429,7 +2429,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* s << INDENT << "PyObject_HEAD_INIT(&Shiboken::SbkBaseWrapperType_Type)" << endl; s << INDENT << "/*ob_size*/ 0," << endl; s << INDENT << "/*tp_name*/ \"" << metaClass->fullName() << "\"," << endl; - s << INDENT << "/*tp_basicsize*/ sizeof(Shiboken::SbkBaseWrapper)," << endl; + s << INDENT << "/*tp_basicsize*/ sizeof(SbkBaseWrapper)," << endl; s << INDENT << "/*tp_itemsize*/ 0," << endl; s << INDENT << "/*tp_dealloc*/ " << tp_dealloc << ',' << endl; s << INDENT << "/*tp_print*/ 0," << endl; diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index ae5b6dda..0e2e7871 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -165,11 +165,11 @@ SbkBaseWrapperType SbkBaseWrapper_Type = { { { void removeParent(SbkBaseWrapper* child) { - ParentInfo* pInfo = child->parentInfo; + ParentInfo* pInfo = child->d->parentInfo; if (!pInfo || !pInfo->parent) return; - ChildrenList& oldBrothers = pInfo->parent->parentInfo->children; + ChildrenList& oldBrothers = pInfo->parent->d->parentInfo->children; oldBrothers.remove(child); pInfo->parent = 0; @@ -205,15 +205,15 @@ void setParent(PyObject* parent, PyObject* child) SbkBaseWrapper* child_ = reinterpret_cast(child); if (!parentIsNull) { - if (!parent_->parentInfo) - parent_->parentInfo = new ParentInfo; + if (!parent_->d->parentInfo) + parent_->d->parentInfo = new ParentInfo; // do not re-add a child - ChildrenList& children = parent_->parentInfo->children; + ChildrenList& children = parent_->d->parentInfo->children; if (std::find(children.begin(), children.end(), child_) != children.end()) return; } - ParentInfo* pInfo = child_->parentInfo; + ParentInfo* pInfo = child_->d->parentInfo; bool hasAnotherParent = pInfo && pInfo->parent && pInfo->parent != parent_; //Avoid destroy child during reparent operation @@ -224,12 +224,12 @@ void setParent(PyObject* parent, PyObject* child) removeParent(child_); // Add the child to the new parent - pInfo = child_->parentInfo; + pInfo = child_->d->parentInfo; if (!parentIsNull) { if (!pInfo) - pInfo = child_->parentInfo = new ParentInfo; + pInfo = child_->d->parentInfo = new ParentInfo; pInfo->parent = parent_; - parent_->parentInfo->children.push_back(child_); + parent_->d->parentInfo->children.push_back(child_); Py_INCREF(child_); } @@ -238,7 +238,7 @@ void setParent(PyObject* parent, PyObject* child) static void _destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent) { - ParentInfo* pInfo = obj->parentInfo; + ParentInfo* pInfo = obj->d->parentInfo; if (removeFromParent && pInfo && pInfo->parent) removeParent(obj); @@ -248,11 +248,9 @@ static void _destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent) SbkBaseWrapper*& child = *it; // keep this, the wrapper still alive - if (!SbkBaseWrapper_containsCppWrapper(obj) && - SbkBaseWrapper_containsCppWrapper(child) && - child->parentInfo) { - child->parentInfo->parent = 0; - child->parentInfo->hasWrapperRef = true; + if (!obj->d->containsCppWrapper && child->d->containsCppWrapper && child->d->parentInfo) { + child->d->parentInfo->parent = 0; + child->d->parentInfo->hasWrapperRef = true; SbkBaseWrapper_setOwnership(child, false); } else { _destroyParentInfo(child, false); @@ -260,7 +258,7 @@ static void _destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent) } } delete pInfo; - obj->parentInfo = 0; + obj->d->parentInfo = 0; } } @@ -288,9 +286,9 @@ PyObject* SbkBaseWrapper_New(SbkBaseWrapperType* instanceType, } SbkBaseWrapper* self = reinterpret_cast(SbkBaseWrapper_TpNew(reinterpret_cast(instanceType), 0, 0)); - self->cptr[0] = cptr; - self->hasOwnership = hasOwnership; - self->validCppObject = 1; + self->d->cptr[0] = cptr; + self->d->hasOwnership = hasOwnership; + self->d->validCppObject = 1; BindingManager::instance().registerWrapper(self, cptr); return reinterpret_cast(self); } @@ -319,18 +317,19 @@ void walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visi PyObject* SbkBaseWrapper_TpNew(PyTypeObject* subtype, PyObject*, PyObject*) { SbkBaseWrapper* self = reinterpret_cast(subtype->tp_alloc(subtype, 0)); + self->d = new SbkBaseWrapperPrivate; SbkBaseWrapperType* sbkType = reinterpret_cast(subtype); int numBases = sbkType->is_multicpp ? getNumberOfCppBaseClasses(subtype) : 1; - self->cptr = new void*[numBases]; - std::memset(self->cptr, 0, sizeof(void*)*numBases); - self->hasOwnership = 1; - self->containsCppWrapper = 0; - self->validCppObject = 0; - self->parentInfo = 0; + self->d->cptr = new void*[numBases]; + std::memset(self->d->cptr, 0, sizeof(void*)*numBases); + self->d->hasOwnership = 1; + self->d->containsCppWrapper = 0; + self->d->validCppObject = 0; + self->d->parentInfo = 0; self->ob_dict = 0; self->weakreflist = 0; - self->referredObjects = 0; + self->d->referredObjects = 0; return reinterpret_cast(self); } @@ -340,7 +339,7 @@ void* getCppPointer(PyObject* wrapper, PyTypeObject* desiredType) int idx = 0; if (reinterpret_cast(type)->is_multicpp) idx = getTypeIndexOnHierarchy(type, desiredType); - return reinterpret_cast(wrapper)->cptr[idx]; + return reinterpret_cast(wrapper)->d->cptr[idx]; } bool setCppPointer(SbkBaseWrapper* wrapper, PyTypeObject* desiredType, void* cptr) @@ -349,11 +348,11 @@ bool setCppPointer(SbkBaseWrapper* wrapper, PyTypeObject* desiredType, void* cpt if (reinterpret_cast(wrapper->ob_type)->is_multicpp) idx = getTypeIndexOnHierarchy(wrapper->ob_type, desiredType); - bool alreadyInitialized = wrapper->cptr[idx]; + bool alreadyInitialized = wrapper->d->cptr[idx]; if (alreadyInitialized) PyErr_SetString(PyExc_RuntimeError, "You can't initialize an object twice!"); else - wrapper->cptr[idx] = cptr; + wrapper->d->cptr[idx] = cptr; return !alreadyInitialized; } @@ -362,7 +361,7 @@ bool cppObjectIsInvalid(PyObject* wrapper) { if (!wrapper || wrapper == Py_None || wrapper->ob_type->ob_type != &Shiboken::SbkBaseWrapperType_Type - || ((Shiboken::SbkBaseWrapper*)wrapper)->validCppObject) { + || ((SbkBaseWrapper*)wrapper)->d->validCppObject) { return false; } PyErr_SetString(PyExc_RuntimeError, "Internal C++ object already deleted."); @@ -399,10 +398,10 @@ void keepReference(SbkBaseWrapper* self, const char* key, PyObject* referredObje bool isNone = (!referredObject || (referredObject == Py_None)); - if (!self->referredObjects) - self->referredObjects = new Shiboken::RefCountMap; + if (!self->d->referredObjects) + self->d->referredObjects = new Shiboken::RefCountMap; - RefCountMap& refCountMap = *(self->referredObjects); + RefCountMap& refCountMap = *(self->d->referredObjects); if (!isNone) incRefPyObject(referredObject); @@ -423,15 +422,15 @@ void keepReference(SbkBaseWrapper* self, const char* key, PyObject* referredObje void clearReferences(SbkBaseWrapper* self) { - if (!self->referredObjects) + if (!self->d->referredObjects) return; - RefCountMap& refCountMap = *(self->referredObjects); + RefCountMap& refCountMap = *(self->d->referredObjects); RefCountMap::iterator iter; for (iter = refCountMap.begin(); iter != refCountMap.end(); ++iter) decRefPyObjectlist(iter->second); - delete self->referredObjects; - self->referredObjects = 0; + delete self->d->referredObjects; + self->d->referredObjects = 0; } bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr) @@ -458,7 +457,7 @@ class DtorCallerVisitor : public HierarchyVisitor DtorCallerVisitor(SbkBaseWrapper* pyObj) : m_count(0), m_pyObj(pyObj) {} virtual void visit(SbkBaseWrapperType* node) { - node->cpp_dtor(m_pyObj->cptr[m_count]); + node->cpp_dtor(m_pyObj->d->cptr[m_count]); m_count++; } private: @@ -473,24 +472,25 @@ void deallocWrapper(PyObject* pyObj) PyObject_ClearWeakRefs(pyObj); BindingManager::instance().releaseWrapper(pyObj); - if (SbkBaseWrapper_hasOwnership(pyObj)) { + if (sbkObj->d->hasOwnership) { SbkBaseWrapperType* sbkType = reinterpret_cast(pyObj->ob_type); if (sbkType->is_multicpp) { DtorCallerVisitor visitor(sbkObj); walkThroughClassHierarchy(pyObj->ob_type, &visitor); } else { - sbkType->cpp_dtor(sbkObj->cptr[0]); + sbkType->cpp_dtor(sbkObj->d->cptr[0]); } } - if (SbkBaseWrapper_hasParentInfo(pyObj)) + if (sbkObj->d->parentInfo) destroyParentInfo(sbkObj); clearReferences(sbkObj); Py_XDECREF(sbkObj->ob_dict); - delete[] sbkObj->cptr; - sbkObj->cptr = 0; + delete[] sbkObj->d->cptr; + sbkObj->d->cptr = 0; + delete sbkObj->d; Py_TYPE(pyObj)->tp_free(pyObj); } @@ -645,7 +645,9 @@ std::list splitPyObject(PyObject* pyObj) if (PySequence_Check(pyObj)) { AutoDecRef lst(PySequence_Fast(pyObj, "Invalid keep reference object.")); for(int i = 0, i_max = PySequence_Fast_GET_SIZE(lst.object()); i < i_max; i++) { - result.push_back(PySequence_Fast_GET_ITEM(lst.object(), i)); + PyObject* item = PySequence_Fast_GET_ITEM(lst.object(), i); + if (isShibokenType(item)) + result.push_back(item); } } else { result.push_back(pyObj); @@ -675,17 +677,40 @@ static void decRefPyObjectlist(const std::list &lst) void SbkBaseWrapper_setOwnership(SbkBaseWrapper* pyobj, bool owner) { - pyobj->hasOwnership = owner; + pyobj->d->hasOwnership = owner; } void SbkBaseWrapper_setOwnership(PyObject* pyobj, bool owner) { - std::list objs = splitPyObject(pyobj); - std::list::const_iterator it; - for(it=objs.begin(); it != objs.end(); it++) - SbkBaseWrapper_setOwnership(reinterpret_cast(*it), owner); + if (PySequence_Check(pyobj)) { + std::list objs = splitPyObject(pyobj); + std::list::const_iterator it; + for(it=objs.begin(); it != objs.end(); it++) + SbkBaseWrapper_setOwnership(reinterpret_cast(*it), owner); + } else if (isShibokenType(pyobj)) { + SbkBaseWrapper_setOwnership(reinterpret_cast(pyobj), owner); + } +} + +namespace Wrapper +{ + +void setValidCpp(SbkBaseWrapper* pyObj, bool value) +{ + pyObj->d->validCppObject = value; +} + +void setHasCppWrapper(SbkBaseWrapper* pyObj, bool value) +{ + pyObj->d->containsCppWrapper = value; +} + +bool hasCppWrapper(SbkBaseWrapper* pyObj) +{ + return pyObj->d->containsCppWrapper; } +} // namespace Wrapper } // namespace Shiboken diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 2440a98c..75fa9040 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -30,14 +30,26 @@ #include #include -namespace Shiboken +extern "C" { -/** - * This mapping associates a method and argument of an wrapper object with the wrapper of - * said argument when it needs the binding to help manage its reference counting. - */ -typedef std::map > RefCountMap; +struct SbkBaseWrapperPrivate; + +/// Base Python object for all the wrapped C++ classes. +struct LIBSHIBOKEN_API SbkBaseWrapper +{ + PyObject_HEAD + /// Instance dictionary. + PyObject* ob_dict; + /// List of weak references + PyObject* weakreflist; + SbkBaseWrapperPrivate* d; +}; + +} + +namespace Shiboken +{ extern "C" { @@ -90,30 +102,6 @@ struct LIBSHIBOKEN_API SbkBaseWrapperType DeleteUserDataFunc d_func; }; -struct ParentInfo; - -/// Base Python object for all the wrapped C++ classes. -struct LIBSHIBOKEN_API SbkBaseWrapper -{ - PyObject_HEAD - /// Pointer to the C++ class. - void** cptr; - /// Instance dictionary. - PyObject* ob_dict; - /// True when Python is responsible for freeing the used memory. - unsigned int hasOwnership : 1; - /// Is true when the C++ class of the wrapped object has a virtual destructor AND was created by Python. - unsigned int containsCppWrapper : 1; - /// Marked as false when the object is lost to C++ and the binding can not know if it was deleted or not. - unsigned int validCppObject : 1; - /// Information about the object parents and children, can be null. - ParentInfo* parentInfo; - /// List of weak references - PyObject* weakreflist; - /// Manage reference counting of objects that are referred but not owned. - RefCountMap* referredObjects; -}; - } // extern "C" /** @@ -187,14 +175,8 @@ LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctor #define SbkBaseWrapper_Check(op) PyObject_TypeCheck(op, (PyTypeObject*)&Shiboken::SbkBaseWrapper_Type) #define SbkBaseWrapper_CheckExact(op) ((op)->ob_type == &Shiboken::SbkBaseWrapper_Type) -#define SbkBaseWrapper_instanceDict(pyobj) (((Shiboken::SbkBaseWrapper*)pyobj)->ob_dict) -#define SbkBaseWrapper_setInstanceDict(pyobj,d) (((Shiboken::SbkBaseWrapper*)pyobj)->ob_dict = d) -#define SbkBaseWrapper_hasOwnership(pyobj) (((Shiboken::SbkBaseWrapper*)pyobj)->hasOwnership) -#define SbkBaseWrapper_hasParentInfo(pyobj) (((Shiboken::SbkBaseWrapper*)pyobj)->parentInfo) -#define SbkBaseWrapper_containsCppWrapper(pyobj) (((Shiboken::SbkBaseWrapper*)pyobj)->containsCppWrapper) -#define SbkBaseWrapper_setContainsCppWrapper(pyobj,o)(((Shiboken::SbkBaseWrapper*)pyobj)->containsCppWrapper = o) -#define SbkBaseWrapper_validCppObject(pyobj) (((Shiboken::SbkBaseWrapper*)pyobj)->validCppObject) -#define SbkBaseWrapper_setValidCppObject(pyobj,v) (((Shiboken::SbkBaseWrapper*)pyobj)->validCppObject = v) +#define SbkBaseWrapper_instanceDict(pyobj) (((SbkBaseWrapper*)pyobj)->ob_dict) +#define SbkBaseWrapper_setInstanceDict(pyobj,d) (((SbkBaseWrapper*)pyobj)->ob_dict = d) LIBSHIBOKEN_API PyObject* SbkBaseWrapper_New(SbkBaseWrapperType* instanceType, @@ -241,6 +223,14 @@ LIBSHIBOKEN_API void setErrorAboutWrongArguments(PyObject* args, const char* fun LIBSHIBOKEN_API void SbkBaseWrapper_setOwnership(PyObject* pyobj, bool owner); LIBSHIBOKEN_API void SbkBaseWrapper_setOwnership(SbkBaseWrapper* pyobj, bool owner); +namespace Wrapper { + +LIBSHIBOKEN_API void setValidCpp(SbkBaseWrapper* pyObj, bool value); +LIBSHIBOKEN_API void setHasCppWrapper(SbkBaseWrapper* pyObj, bool value); +LIBSHIBOKEN_API bool hasCppWrapper(SbkBaseWrapper* pyObj); + +} // namespace Wrapper + } // namespace Shiboken #endif // BASEWRAPPER_H diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h index 20476d3a..a07f5482 100644 --- a/libshiboken/basewrapper_p.h +++ b/libshiboken/basewrapper_p.h @@ -25,11 +25,66 @@ #include #include +#include + +struct SbkBaseWrapper; + +namespace Shiboken +{ +/** + * This mapping associates a method and argument of an wrapper object with the wrapper of + * said argument when it needs the binding to help manage its reference counting. + */ +typedef std::map > RefCountMap; + + +/// Linked list of SbkBaseWrapper pointers +typedef std::list ChildrenList; + +/// Struct used to store information about object parent and children. +struct ParentInfo +{ + /// Default ctor. + ParentInfo() : parent(0), hasWrapperRef(false) {} + /// Pointer to parent object. + SbkBaseWrapper* parent; + /// List of object children. + ChildrenList children; + /// has internal ref + bool hasWrapperRef; +}; + +} // namespace Shiboken + +extern "C" +{ + +/** + * \internal + * Private data for SbkBaseWrapper + */ +struct SbkBaseWrapperPrivate +{ + /// Pointer to the C++ class. + void** cptr; + /// True when Python is responsible for freeing the used memory. + unsigned int hasOwnership : 1; + /// Is true when the C++ class of the wrapped object has a virtual destructor AND was created by Python. + unsigned int containsCppWrapper : 1; + /// Marked as false when the object is lost to C++ and the binding can not know if it was deleted or not. + unsigned int validCppObject : 1; + /// Information about the object parents and children, can be null. + Shiboken::ParentInfo* parentInfo; + /// Manage reference counting of objects that are referred but not owned. + Shiboken::RefCountMap* referredObjects; +}; + +} // extern "C" namespace Shiboken { /** - * Utility function uset to transform PyObject which suppot sequence protocol in a std::list + * Utility function uset to transform PyObject which suppot sequence protocol in a std::list **/ std::list splitPyObject(PyObject* pyObj); @@ -126,30 +181,12 @@ inline std::list getCppBaseClasses(PyTypeObject* baseType) return visitor.bases(); } -struct SbkBaseWrapper; - -/// Linked list of SbkBaseWrapper pointers -typedef std::list ChildrenList; - -/// Struct used to store information about object parent and children. -struct ParentInfo -{ - /// Default ctor. - ParentInfo() : parent(0), hasWrapperRef(false) {} - /// Pointer to parent object. - SbkBaseWrapper* parent; - /// List of object children. - ChildrenList children; - /// has internal ref - bool hasWrapperRef; -}; - /** * Decrements the reference counters of every object referred by self. * \param self the wrapper instance that keeps references to other objects. */ void clearReferences(SbkBaseWrapper* self); -} +} // namespace Shiboken #endif diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index 38dc4eb8..22bfde74 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -184,7 +184,7 @@ void BindingManager::releaseWrapper(PyObject* wrapper) SbkBaseWrapperType* sbkType = reinterpret_cast(wrapper->ob_type); int numBases = sbkType->is_multicpp ? getNumberOfCppBaseClasses(wrapper->ob_type) : 1; - void** cptrs = reinterpret_cast(wrapper)->cptr; + void** cptrs = reinterpret_cast(wrapper)->d->cptr; for (int i = 0; i < numBases; ++i) { void* cptr = cptrs[i]; m_d->releaseWrapper(cptr); @@ -258,32 +258,32 @@ void BindingManager::invalidateWrapper(PyObject* pyobj) void BindingManager::invalidateWrapper(SbkBaseWrapper* wrapper) { - if (!wrapper || ((PyObject*)wrapper == Py_None) || !SbkBaseWrapper_validCppObject(wrapper)) + if (!wrapper || ((PyObject*)wrapper == Py_None) || !wrapper->d->validCppObject) return; GilState gil; // lock the gil to assure no one is changing the value of m_d->destroying // skip this if the object is a wrapper class and this is not a destructor call - if (SbkBaseWrapper_containsCppWrapper(wrapper) && !m_d->destroying) { - ParentInfo* pInfo = wrapper->parentInfo; + if (wrapper->d->containsCppWrapper && !m_d->destroying) { + ParentInfo* pInfo = wrapper->d->parentInfo; // this meaning the object has a extra ref and we will remove this now if (pInfo && pInfo->hasWrapperRef) { delete pInfo; - wrapper->parentInfo = 0; + wrapper->d->parentInfo = 0; Py_XDECREF((PyObject*) wrapper); } return; } - SbkBaseWrapper_setValidCppObject(wrapper, false); - SbkBaseWrapper_setOwnership(wrapper, false); + wrapper->d->validCppObject = false; + wrapper->d->hasOwnership = false; // If it is a parent invalidate all children. - if (SbkBaseWrapper_hasParentInfo(wrapper)) { - ChildrenList::iterator it = wrapper->parentInfo->children.begin(); + if (wrapper->d->parentInfo) { + ChildrenList::iterator it = wrapper->d->parentInfo->children.begin(); bool parentDestroying = m_d->destroying; m_d->destroying = false; - for (; it != wrapper->parentInfo->children.end(); ++it) + for (; it != wrapper->d->parentInfo->children.end(); ++it) invalidateWrapper(*it); m_d->destroying = parentDestroying; } @@ -323,10 +323,10 @@ void BindingManager::transferOwnershipToCpp(PyObject* wrapper) void BindingManager::transferOwnershipToCpp(SbkBaseWrapper* wrapper) { - if (wrapper->parentInfo) + if (wrapper->d->parentInfo) Shiboken::removeParent(wrapper); - if (SbkBaseWrapper_containsCppWrapper(wrapper)) + if (wrapper->d->containsCppWrapper) SbkBaseWrapper_setOwnership(wrapper, false); else invalidateWrapper(wrapper); diff --git a/libshiboken/bindingmanager.h b/libshiboken/bindingmanager.h index d7cec27b..b5bf43b6 100644 --- a/libshiboken/bindingmanager.h +++ b/libshiboken/bindingmanager.h @@ -27,10 +27,11 @@ #include #include "shibokenmacros.h" +struct SbkBaseWrapper; + namespace Shiboken { -struct SbkBaseWrapper; struct SbkBaseWrapperType; class LIBSHIBOKEN_API BindingManager @@ -40,7 +41,7 @@ class LIBSHIBOKEN_API BindingManager bool hasWrapper(const void *cptr); - void registerWrapper( Shiboken::SbkBaseWrapper* pyobj, void* cptr); + void registerWrapper(SbkBaseWrapper* pyobj, void* cptr); void releaseWrapper(PyObject* wrapper); PyObject* retrieveWrapper(const void* cptr); PyObject* getOverride(const void* cptr, const char* methodName); diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index 67e62792..b077e2f2 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -223,8 +223,8 @@ struct ValueTypeConverter static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } static inline PyObject* toPython(const T& cppobj) { - PyObject* obj = createWrapper(CppObjectCopier::copy(cppobj), true, true); - SbkBaseWrapper_setContainsCppWrapper(obj, SbkTypeInfo::isCppWrapper); + PyObject* obj = createWrapper(new T(cppobj), true, true); +// SbkBaseWrapper_setContainsCppWrapper(obj, SbkTypeInfo::isCppWrapper); return obj; } // Classes with implicit conversions are expected to reimplement 'toCpp' to build T from From f1ad9bf233f1fe88e72d350caaffc5164ce20511 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 9 Nov 2010 17:38:21 -0200 Subject: [PATCH 108/564] Replaced SbkBaseWrapper_setOwnership by getOwnership and releaseOwnership (both inside Shiboken:Wrapper namespace) --- generator/cppgenerator.cpp | 6 +-- libshiboken/basewrapper.cpp | 69 +++++++++++++++++++++------------- libshiboken/basewrapper.h | 9 +++-- libshiboken/basewrapper_p.h | 4 +- libshiboken/bindingmanager.cpp | 18 ++++----- 5 files changed, 62 insertions(+), 44 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index fe623953..2ab4bfdc 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2121,10 +2121,10 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f s << INDENT; if (arg_mod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::TargetLangOwnership) { - s << "SbkBaseWrapper_setOwnership(" << pyArgName << ", true);"; + s << "Shiboken::Wrapper::getOwnership(" << pyArgName << ");"; } else if (wrappedClass->hasVirtualDestructor()) { if (arg_mod.index == 0) { - s << "SbkBaseWrapper_setOwnership(" PYTHON_RETURN_VAR ", 0);"; + s << "Shiboken::Wrapper::releaseOwnership(" PYTHON_RETURN_VAR ");"; } else { s << "BindingManager::instance().transferOwnershipToCpp(" << pyArgName << ");"; } @@ -2666,7 +2666,7 @@ void CppGenerator::writeCopyFunction(QTextStream& s, const AbstractMetaClass *me s << INDENT << PYTHON_RETURN_VAR " = Shiboken::Converter<" << metaClass->qualifiedCppName(); s << "*>::toPython(copy);" << endl; - s << INDENT << "SbkBaseWrapper_setOwnership(" PYTHON_RETURN_VAR ", true);" << endl; + s << INDENT << "Shiboken::Wrapper::getOwnership(" PYTHON_RETURN_VAR ");" << endl; s << endl; diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 0e2e7871..7c0e7a4e 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -36,7 +36,7 @@ namespace Shiboken static void SbkBaseWrapperType_dealloc(PyObject* pyObj); static PyObject* SbkBaseWrapperType_TpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds); static void incRefPyObject(PyObject* pyObj); -static void decRefPyObjectlist(const std::list &pyObj); +static void decRefPyObjectlist(const std::list &pyObj); extern "C" { @@ -251,7 +251,7 @@ static void _destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent) if (!obj->d->containsCppWrapper && child->d->containsCppWrapper && child->d->parentInfo) { child->d->parentInfo->parent = 0; child->d->parentInfo->hasWrapperRef = true; - SbkBaseWrapper_setOwnership(child, false); + child->d->hasOwnership = false; } else { _destroyParentInfo(child, false); Py_DECREF(child); @@ -412,7 +412,7 @@ void keepReference(SbkBaseWrapper* self, const char* key, PyObject* referredObje } if (!isNone) { - std::list values = splitPyObject(referredObject); + std::list values = splitPyObject(referredObject); if (append && (iter != refCountMap.end())) refCountMap[key].insert(refCountMap[key].end(), values.begin(), values.end()); else @@ -639,18 +639,20 @@ bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType) return true; } -std::list splitPyObject(PyObject* pyObj) +std::list splitPyObject(PyObject* pyObj) { - std::list result; + std::list result; if (PySequence_Check(pyObj)) { AutoDecRef lst(PySequence_Fast(pyObj, "Invalid keep reference object.")); - for(int i = 0, i_max = PySequence_Fast_GET_SIZE(lst.object()); i < i_max; i++) { - PyObject* item = PySequence_Fast_GET_ITEM(lst.object(), i); - if (isShibokenType(item)) - result.push_back(item); + if (!lst.isNull()) { + for(int i = 0, i_max = PySequence_Fast_GET_SIZE(lst.object()); i < i_max; i++) { + PyObject* item = PySequence_Fast_GET_ITEM(lst.object(), i); + if (isShibokenType(item)) + result.push_back(reinterpret_cast(item)); + } } } else { - result.push_back(pyObj); + result.push_back(reinterpret_cast(pyObj)); } return result; } @@ -666,29 +668,24 @@ static void incRefPyObject(PyObject* pyObj) } } -static void decRefPyObjectlist(const std::list &lst) +static void decRefPyObjectlist(const std::list &lst) { - std::list::const_iterator iter = lst.begin(); + std::list::const_iterator iter = lst.begin(); while(iter != lst.end()) { Py_DECREF(*iter); - iter++; + ++iter; } } -void SbkBaseWrapper_setOwnership(SbkBaseWrapper* pyobj, bool owner) +static void setSequenceOwnership(PyObject* pyObj, bool owner) { - pyobj->d->hasOwnership = owner; -} - -void SbkBaseWrapper_setOwnership(PyObject* pyobj, bool owner) -{ - if (PySequence_Check(pyobj)) { - std::list objs = splitPyObject(pyobj); - std::list::const_iterator it; - for(it=objs.begin(); it != objs.end(); it++) - SbkBaseWrapper_setOwnership(reinterpret_cast(*it), owner); - } else if (isShibokenType(pyobj)) { - SbkBaseWrapper_setOwnership(reinterpret_cast(pyobj), owner); + if (PySequence_Check(pyObj)) { + std::list objs = splitPyObject(pyObj); + std::list::const_iterator it = objs.begin(); + for(; it != objs.end(); ++it) + (*it)->d->hasOwnership = owner; + } else if (isShibokenType(pyObj)) { + reinterpret_cast(pyObj)->d->hasOwnership = owner; } } @@ -710,6 +707,26 @@ bool hasCppWrapper(SbkBaseWrapper* pyObj) return pyObj->d->containsCppWrapper; } +void getOwnership(SbkBaseWrapper* pyObj) +{ + pyObj->d->hasOwnership = true; +} + +void getOwnership(PyObject* pyObj) +{ + setSequenceOwnership(pyObj, true); +} + +void releaseOwnership(SbkBaseWrapper* pyObj) +{ + pyObj->d->hasOwnership = false; +} + +void releaseOwnership(PyObject* pyObj) +{ + setSequenceOwnership(pyObj, false); +} + } // namespace Wrapper } // namespace Shiboken diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 75fa9040..5d0d4728 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -219,16 +219,17 @@ LIBSHIBOKEN_API void deallocWrapperWithPrivateDtor(PyObject* self); LIBSHIBOKEN_API bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr); LIBSHIBOKEN_API void setErrorAboutWrongArguments(PyObject* args, const char* funcName, const char** cppOverloads); -/// Support sequence protocol -LIBSHIBOKEN_API void SbkBaseWrapper_setOwnership(PyObject* pyobj, bool owner); -LIBSHIBOKEN_API void SbkBaseWrapper_setOwnership(SbkBaseWrapper* pyobj, bool owner); - namespace Wrapper { LIBSHIBOKEN_API void setValidCpp(SbkBaseWrapper* pyObj, bool value); LIBSHIBOKEN_API void setHasCppWrapper(SbkBaseWrapper* pyObj, bool value); LIBSHIBOKEN_API bool hasCppWrapper(SbkBaseWrapper* pyObj); +LIBSHIBOKEN_API void getOwnership(PyObject* pyobj); +LIBSHIBOKEN_API void getOwnership(SbkBaseWrapper* pyobj); +LIBSHIBOKEN_API void releaseOwnership(PyObject* pyobj); +LIBSHIBOKEN_API void releaseOwnership(SbkBaseWrapper* pyobj); + } // namespace Wrapper } // namespace Shiboken diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h index a07f5482..1a72781d 100644 --- a/libshiboken/basewrapper_p.h +++ b/libshiboken/basewrapper_p.h @@ -35,7 +35,7 @@ namespace Shiboken * This mapping associates a method and argument of an wrapper object with the wrapper of * said argument when it needs the binding to help manage its reference counting. */ -typedef std::map > RefCountMap; +typedef std::map > RefCountMap; /// Linked list of SbkBaseWrapper pointers @@ -86,7 +86,7 @@ namespace Shiboken /** * Utility function uset to transform PyObject which suppot sequence protocol in a std::list **/ -std::list splitPyObject(PyObject* pyObj); +std::list splitPyObject(PyObject* pyObj); struct SbkBaseWrapperType; diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index 22bfde74..5e9be699 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -250,10 +250,10 @@ PyObject* BindingManager::getOverride(const void* cptr, const char* methodName) void BindingManager::invalidateWrapper(PyObject* pyobj) { - std::list objs = splitPyObject(pyobj); - std::list::const_iterator it; - for(it=objs.begin(); it != objs.end(); it++) - invalidateWrapper(reinterpret_cast(*it)); + std::list objs = splitPyObject(pyobj); + std::list::const_iterator it = objs.begin(); + for(; it != objs.end(); it++) + invalidateWrapper(*it); } void BindingManager::invalidateWrapper(SbkBaseWrapper* wrapper) @@ -315,10 +315,10 @@ void BindingManager::destroyWrapper(SbkBaseWrapper* wrapper) void BindingManager::transferOwnershipToCpp(PyObject* wrapper) { - std::list objs = splitPyObject(wrapper); - std::list::const_iterator it; - for(it=objs.begin(); it != objs.end(); it++) - transferOwnershipToCpp(reinterpret_cast(*it)); + std::list objs = splitPyObject(wrapper); + std::list::const_iterator it = objs.begin(); + for(; it != objs.end(); it++) + transferOwnershipToCpp(*it); } void BindingManager::transferOwnershipToCpp(SbkBaseWrapper* wrapper) @@ -327,7 +327,7 @@ void BindingManager::transferOwnershipToCpp(SbkBaseWrapper* wrapper) Shiboken::removeParent(wrapper); if (wrapper->d->containsCppWrapper) - SbkBaseWrapper_setOwnership(wrapper, false); + wrapper->d->hasOwnership = false; else invalidateWrapper(wrapper); } From 0949f2b49dcfd9516e4e3e4044a97070533799ad Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 9 Nov 2010 17:47:10 -0200 Subject: [PATCH 109/564] SbkBaseWrapper renamed to SbkObject --- generator/cppgenerator.cpp | 14 +++--- libshiboken/basewrapper.cpp | 82 +++++++++++++++++----------------- libshiboken/basewrapper.h | 32 ++++++------- libshiboken/basewrapper_p.h | 12 ++--- libshiboken/bindingmanager.cpp | 20 ++++----- libshiboken/bindingmanager.h | 10 ++--- 6 files changed, 85 insertions(+), 85 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 2ab4bfdc..4f4498ac 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -779,13 +779,13 @@ void CppGenerator::writeMetaObjectMethod(QTextStream& s, const AbstractMetaClass { Indentation indentation(INDENT); s << INDENT << "PyObject *pySelf = BindingManager::instance().retrieveWrapper(this);\n" - << INDENT << "void *typeData = Shiboken::getTypeUserData(reinterpret_cast(pySelf));" << endl + << INDENT << "void *typeData = Shiboken::getTypeUserData(reinterpret_cast(pySelf));" << endl << INDENT << "if (!typeData) {" << endl; { Indentation indentation2(INDENT); s << INDENT << "m_metaObject = PySide::DynamicQMetaObject::createBasedOn(pySelf, pySelf->ob_type, &" << metaClass->qualifiedCppName() << "::staticMetaObject);" << endl - << INDENT << "Shiboken::setTypeUserData(reinterpret_cast(pySelf), m_metaObject, PySide::deleteDynamicQMetaObject);" << endl; + << INDENT << "Shiboken::setTypeUserData(reinterpret_cast(pySelf), m_metaObject, PySide::deleteDynamicQMetaObject);" << endl; } s << INDENT << "} else {" << endl; { @@ -854,7 +854,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun s << INDENT << "const QMetaObject* metaObject;" << endl; } - s << INDENT << "SbkBaseWrapper* sbkSelf = reinterpret_cast(self);" << endl; + s << INDENT << "SbkObject* sbkSelf = reinterpret_cast(self);" << endl; if (metaClass->isAbstract() || metaClass->baseClassNames().size() > 1) { s << INDENT << "SbkBaseWrapperType* type = reinterpret_cast(self->ob_type);" << endl; @@ -1843,7 +1843,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f } if (func->isAbstract()) { - s << INDENT << "if (Shiboken::Wrapper::hasCppWrapper(reinterpret_cast(self))) {\n"; + s << INDENT << "if (Shiboken::Wrapper::hasCppWrapper(reinterpret_cast(self))) {\n"; { Indentation indent(INDENT); s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '"; @@ -2145,7 +2145,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f break; } - s << INDENT << "Shiboken::keepReference(reinterpret_cast(self), \""; + s << INDENT << "Shiboken::keepReference(reinterpret_cast(self), \""; QString varName = arg_mod.referenceCounts.first().varName; if (varName.isEmpty()) varName = func->minimalSignature() + QString().number(arg_mod.index); @@ -2429,7 +2429,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* s << INDENT << "PyObject_HEAD_INIT(&Shiboken::SbkBaseWrapperType_Type)" << endl; s << INDENT << "/*ob_size*/ 0," << endl; s << INDENT << "/*tp_name*/ \"" << metaClass->fullName() << "\"," << endl; - s << INDENT << "/*tp_basicsize*/ sizeof(SbkBaseWrapper)," << endl; + s << INDENT << "/*tp_basicsize*/ sizeof(SbkObject)," << endl; s << INDENT << "/*tp_itemsize*/ 0," << endl; s << INDENT << "/*tp_dealloc*/ " << tp_dealloc << ',' << endl; s << INDENT << "/*tp_print*/ 0," << endl; @@ -2748,7 +2748,7 @@ void CppGenerator::writeSetterFunction(QTextStream& s, const AbstractMetaField* bool pythonWrapperRefCounting = metaField->type()->typeEntry()->isObject() || metaField->type()->isValuePointer(); if (pythonWrapperRefCounting) { - s << INDENT << "Shiboken::keepReference(reinterpret_cast(self), \""; + s << INDENT << "Shiboken::keepReference(reinterpret_cast(self), \""; s << metaField->name() << "\", value);" << endl; //s << INDENT << "Py_XDECREF(oldvalue);" << endl; s << endl; diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 7c0e7a4e..a1813350 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -36,7 +36,7 @@ namespace Shiboken static void SbkBaseWrapperType_dealloc(PyObject* pyObj); static PyObject* SbkBaseWrapperType_TpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds); static void incRefPyObject(PyObject* pyObj); -static void decRefPyObjectlist(const std::list &pyObj); +static void decRefPyObjectlist(const std::list &pyObj); extern "C" { @@ -90,7 +90,7 @@ PyTypeObject SbkBaseWrapperType_Type = { /*tp_weaklist*/ 0 }; -static PyObject* SbkBaseWrapper_get_dict(SbkBaseWrapper* obj) +static PyObject* SbkBaseWrapper_get_dict(SbkObject* obj) { if (!obj->ob_dict) obj->ob_dict = PyDict_New(); @@ -109,7 +109,7 @@ SbkBaseWrapperType SbkBaseWrapper_Type = { { { PyObject_HEAD_INIT(&SbkBaseWrapperType_Type) /*ob_size*/ 0, /*tp_name*/ "Shiboken.BaseWrapper", - /*tp_basicsize*/ sizeof(SbkBaseWrapper), + /*tp_basicsize*/ sizeof(SbkObject), /*tp_itemsize*/ 0, /*tp_dealloc*/ deallocWrapperWithPrivateDtor, /*tp_print*/ 0, @@ -131,7 +131,7 @@ SbkBaseWrapperType SbkBaseWrapper_Type = { { { /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ 0, - /*tp_weaklistoffset*/ offsetof(SbkBaseWrapper, weakreflist), + /*tp_weaklistoffset*/ offsetof(SbkObject, weakreflist), /*tp_iter*/ 0, /*tp_iternext*/ 0, /*tp_methods*/ 0, @@ -141,7 +141,7 @@ SbkBaseWrapperType SbkBaseWrapper_Type = { { { /*tp_dict*/ 0, /*tp_descr_get*/ 0, /*tp_descr_set*/ 0, - /*tp_dictoffset*/ offsetof(SbkBaseWrapper, ob_dict), + /*tp_dictoffset*/ offsetof(SbkObject, ob_dict), /*tp_init*/ 0, /*tp_alloc*/ 0, /*tp_new*/ 0, @@ -163,7 +163,7 @@ SbkBaseWrapperType SbkBaseWrapper_Type = { { { } //extern "C" -void removeParent(SbkBaseWrapper* child) +void removeParent(SbkObject* child) { ParentInfo* pInfo = child->d->parentInfo; if (!pInfo || !pInfo->parent) @@ -201,8 +201,8 @@ void setParent(PyObject* parent, PyObject* child) } bool parentIsNull = !parent || parent == Py_None; - SbkBaseWrapper* parent_ = reinterpret_cast(parent); - SbkBaseWrapper* child_ = reinterpret_cast(child); + SbkObject* parent_ = reinterpret_cast(parent); + SbkObject* child_ = reinterpret_cast(child); if (!parentIsNull) { if (!parent_->d->parentInfo) @@ -236,7 +236,7 @@ void setParent(PyObject* parent, PyObject* child) Py_DECREF(child); } -static void _destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent) +static void _destroyParentInfo(SbkObject* obj, bool removeFromParent) { ParentInfo* pInfo = obj->d->parentInfo; if (removeFromParent && pInfo && pInfo->parent) @@ -245,7 +245,7 @@ static void _destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent) if (pInfo) { ChildrenList::iterator it = pInfo->children.begin(); for (; it != pInfo->children.end(); ++it) { - SbkBaseWrapper*& child = *it; + SbkObject*& child = *it; // keep this, the wrapper still alive if (!obj->d->containsCppWrapper && child->d->containsCppWrapper && child->d->parentInfo) { @@ -262,7 +262,7 @@ static void _destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent) } } -void destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent) +void destroyParentInfo(SbkObject* obj, bool removeFromParent) { BindingManager::instance().destroyWrapper(obj); _destroyParentInfo(obj, removeFromParent); @@ -285,7 +285,7 @@ PyObject* SbkBaseWrapper_New(SbkBaseWrapperType* instanceType, instanceType = BindingManager::instance().resolveType(cptr, instanceType); } - SbkBaseWrapper* self = reinterpret_cast(SbkBaseWrapper_TpNew(reinterpret_cast(instanceType), 0, 0)); + SbkObject* self = reinterpret_cast(SbkBaseWrapper_TpNew(reinterpret_cast(instanceType), 0, 0)); self->d->cptr[0] = cptr; self->d->hasOwnership = hasOwnership; self->d->validCppObject = 1; @@ -316,7 +316,7 @@ void walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visi PyObject* SbkBaseWrapper_TpNew(PyTypeObject* subtype, PyObject*, PyObject*) { - SbkBaseWrapper* self = reinterpret_cast(subtype->tp_alloc(subtype, 0)); + SbkObject* self = reinterpret_cast(subtype->tp_alloc(subtype, 0)); self->d = new SbkBaseWrapperPrivate; SbkBaseWrapperType* sbkType = reinterpret_cast(subtype); @@ -339,10 +339,10 @@ void* getCppPointer(PyObject* wrapper, PyTypeObject* desiredType) int idx = 0; if (reinterpret_cast(type)->is_multicpp) idx = getTypeIndexOnHierarchy(type, desiredType); - return reinterpret_cast(wrapper)->d->cptr[idx]; + return reinterpret_cast(wrapper)->d->cptr[idx]; } -bool setCppPointer(SbkBaseWrapper* wrapper, PyTypeObject* desiredType, void* cptr) +bool setCppPointer(SbkObject* wrapper, PyTypeObject* desiredType, void* cptr) { int idx = 0; if (reinterpret_cast(wrapper->ob_type)->is_multicpp) @@ -361,14 +361,14 @@ bool cppObjectIsInvalid(PyObject* wrapper) { if (!wrapper || wrapper == Py_None || wrapper->ob_type->ob_type != &Shiboken::SbkBaseWrapperType_Type - || ((SbkBaseWrapper*)wrapper)->d->validCppObject) { + || ((SbkObject*)wrapper)->d->validCppObject) { return false; } PyErr_SetString(PyExc_RuntimeError, "Internal C++ object already deleted."); return true; } -void setTypeUserData(SbkBaseWrapper* wrapper, void *user_data, DeleteUserDataFunc d_func) +void setTypeUserData(SbkObject* wrapper, void *user_data, DeleteUserDataFunc d_func) { SbkBaseWrapperType* ob_type = reinterpret_cast(wrapper->ob_type); if (ob_type->user_data) @@ -378,22 +378,22 @@ void setTypeUserData(SbkBaseWrapper* wrapper, void *user_data, DeleteUserDataFun ob_type->user_data = user_data; } -void* getTypeUserData(SbkBaseWrapper* wrapper) +void* getTypeUserData(SbkObject* wrapper) { return reinterpret_cast(wrapper->ob_type)->user_data; } void deallocWrapperWithPrivateDtor(PyObject* self) { - if (((SbkBaseWrapper *)self)->weakreflist) + if (((SbkObject *)self)->weakreflist) PyObject_ClearWeakRefs(self); BindingManager::instance().releaseWrapper(self); - clearReferences(reinterpret_cast(self)); - Py_TYPE(reinterpret_cast(self))->tp_free(self); + clearReferences(reinterpret_cast(self)); + Py_TYPE(reinterpret_cast(self))->tp_free(self); } -void keepReference(SbkBaseWrapper* self, const char* key, PyObject* referredObject, bool append) +void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append) { bool isNone = (!referredObject || (referredObject == Py_None)); @@ -412,7 +412,7 @@ void keepReference(SbkBaseWrapper* self, const char* key, PyObject* referredObje } if (!isNone) { - std::list values = splitPyObject(referredObject); + std::list values = splitPyObject(referredObject); if (append && (iter != refCountMap.end())) refCountMap[key].insert(refCountMap[key].end(), values.begin(), values.end()); else @@ -420,7 +420,7 @@ void keepReference(SbkBaseWrapper* self, const char* key, PyObject* referredObje } } -void clearReferences(SbkBaseWrapper* self) +void clearReferences(SbkObject* self) { if (!self->d->referredObjects) return; @@ -454,7 +454,7 @@ bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr) class DtorCallerVisitor : public HierarchyVisitor { public: - DtorCallerVisitor(SbkBaseWrapper* pyObj) : m_count(0), m_pyObj(pyObj) {} + DtorCallerVisitor(SbkObject* pyObj) : m_count(0), m_pyObj(pyObj) {} virtual void visit(SbkBaseWrapperType* node) { node->cpp_dtor(m_pyObj->d->cptr[m_count]); @@ -462,12 +462,12 @@ class DtorCallerVisitor : public HierarchyVisitor } private: int m_count; - SbkBaseWrapper* m_pyObj; + SbkObject* m_pyObj; }; void deallocWrapper(PyObject* pyObj) { - SbkBaseWrapper* sbkObj = reinterpret_cast(pyObj); + SbkObject* sbkObj = reinterpret_cast(pyObj); if (sbkObj->weakreflist) PyObject_ClearWeakRefs(pyObj); @@ -639,20 +639,20 @@ bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType) return true; } -std::list splitPyObject(PyObject* pyObj) +std::list splitPyObject(PyObject* pyObj) { - std::list result; + std::list result; if (PySequence_Check(pyObj)) { AutoDecRef lst(PySequence_Fast(pyObj, "Invalid keep reference object.")); if (!lst.isNull()) { for(int i = 0, i_max = PySequence_Fast_GET_SIZE(lst.object()); i < i_max; i++) { PyObject* item = PySequence_Fast_GET_ITEM(lst.object(), i); if (isShibokenType(item)) - result.push_back(reinterpret_cast(item)); + result.push_back(reinterpret_cast(item)); } } } else { - result.push_back(reinterpret_cast(pyObj)); + result.push_back(reinterpret_cast(pyObj)); } return result; } @@ -668,9 +668,9 @@ static void incRefPyObject(PyObject* pyObj) } } -static void decRefPyObjectlist(const std::list &lst) +static void decRefPyObjectlist(const std::list &lst) { - std::list::const_iterator iter = lst.begin(); + std::list::const_iterator iter = lst.begin(); while(iter != lst.end()) { Py_DECREF(*iter); ++iter; @@ -680,34 +680,34 @@ static void decRefPyObjectlist(const std::list &lst) static void setSequenceOwnership(PyObject* pyObj, bool owner) { if (PySequence_Check(pyObj)) { - std::list objs = splitPyObject(pyObj); - std::list::const_iterator it = objs.begin(); + std::list objs = splitPyObject(pyObj); + std::list::const_iterator it = objs.begin(); for(; it != objs.end(); ++it) (*it)->d->hasOwnership = owner; } else if (isShibokenType(pyObj)) { - reinterpret_cast(pyObj)->d->hasOwnership = owner; + reinterpret_cast(pyObj)->d->hasOwnership = owner; } } namespace Wrapper { -void setValidCpp(SbkBaseWrapper* pyObj, bool value) +void setValidCpp(SbkObject* pyObj, bool value) { pyObj->d->validCppObject = value; } -void setHasCppWrapper(SbkBaseWrapper* pyObj, bool value) +void setHasCppWrapper(SbkObject* pyObj, bool value) { pyObj->d->containsCppWrapper = value; } -bool hasCppWrapper(SbkBaseWrapper* pyObj) +bool hasCppWrapper(SbkObject* pyObj) { return pyObj->d->containsCppWrapper; } -void getOwnership(SbkBaseWrapper* pyObj) +void getOwnership(SbkObject* pyObj) { pyObj->d->hasOwnership = true; } @@ -717,7 +717,7 @@ void getOwnership(PyObject* pyObj) setSequenceOwnership(pyObj, true); } -void releaseOwnership(SbkBaseWrapper* pyObj) +void releaseOwnership(SbkObject* pyObj) { pyObj->d->hasOwnership = false; } diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 5d0d4728..51ee7f8d 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -36,7 +36,7 @@ extern "C" struct SbkBaseWrapperPrivate; /// Base Python object for all the wrapped C++ classes. -struct LIBSHIBOKEN_API SbkBaseWrapper +struct LIBSHIBOKEN_API SbkObject { PyObject_HEAD /// Instance dictionary. @@ -121,13 +121,13 @@ LIBSHIBOKEN_API void setParent(PyObject* parent, PyObject* child); * Remove this child from their parent, if any. * \param child the child. */ -LIBSHIBOKEN_API void removeParent(SbkBaseWrapper* child); +LIBSHIBOKEN_API void removeParent(SbkObject* child); /** * \internal This is an internal function called by SbkBaseWrapper_Dealloc, it's exported just for techinical reasons. * \note Do not call this function inside your bindings. */ -LIBSHIBOKEN_API void destroyParentInfo(SbkBaseWrapper* obj, bool removeFromParent = true); +LIBSHIBOKEN_API void destroyParentInfo(SbkObject* obj, bool removeFromParent = true); /** * Returns true if the object is an instance of a type created by the Shiboken generator. @@ -153,13 +153,13 @@ LIBSHIBOKEN_API void* getCppPointer(PyObject* wrapper, PyTypeObject* desiredType /** * Set the C++ pointer of type \p desiredType of a Python object. */ -LIBSHIBOKEN_API bool setCppPointer(SbkBaseWrapper* wrapper, PyTypeObject* desiredType, void* cptr); +LIBSHIBOKEN_API bool setCppPointer(SbkObject* wrapper, PyTypeObject* desiredType, void* cptr); /** * Get/Set Userdata in type class */ -LIBSHIBOKEN_API void setTypeUserData(SbkBaseWrapper* wrapper, void* user_data, DeleteUserDataFunc d_func); -LIBSHIBOKEN_API void* getTypeUserData(SbkBaseWrapper* wrapper); +LIBSHIBOKEN_API void setTypeUserData(SbkObject* wrapper, void* user_data, DeleteUserDataFunc d_func); +LIBSHIBOKEN_API void* getTypeUserData(SbkObject* wrapper); /** * Returns true if the constructor of \p ctorType can be called for a instance of type \p myType. @@ -175,8 +175,8 @@ LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctor #define SbkBaseWrapper_Check(op) PyObject_TypeCheck(op, (PyTypeObject*)&Shiboken::SbkBaseWrapper_Type) #define SbkBaseWrapper_CheckExact(op) ((op)->ob_type == &Shiboken::SbkBaseWrapper_Type) -#define SbkBaseWrapper_instanceDict(pyobj) (((SbkBaseWrapper*)pyobj)->ob_dict) -#define SbkBaseWrapper_setInstanceDict(pyobj,d) (((SbkBaseWrapper*)pyobj)->ob_dict = d) +#define SbkBaseWrapper_instanceDict(pyobj) (((SbkObject*)pyobj)->ob_dict) +#define SbkBaseWrapper_setInstanceDict(pyobj,d) (((SbkObject*)pyobj)->ob_dict = d) LIBSHIBOKEN_API PyObject* SbkBaseWrapper_New(SbkBaseWrapperType* instanceType, @@ -200,7 +200,7 @@ SbkBaseWrapper_TpNew(PyTypeObject* subtype, PyObject*, PyObject*); * \param key a key that identifies the C++ method signature and argument where the referredObject came from. * \parem referredObject the object whose reference is used by the self object. */ -LIBSHIBOKEN_API void keepReference(SbkBaseWrapper* self, const char* key, PyObject* referredObject, bool append=false); +LIBSHIBOKEN_API void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append=false); /// Returns true and sets a Python RuntimeError if the Python wrapper is not marked as valid. LIBSHIBOKEN_API bool cppObjectIsInvalid(PyObject* wrapper); @@ -221,14 +221,14 @@ LIBSHIBOKEN_API void setErrorAboutWrongArguments(PyObject* args, const char* fun namespace Wrapper { -LIBSHIBOKEN_API void setValidCpp(SbkBaseWrapper* pyObj, bool value); -LIBSHIBOKEN_API void setHasCppWrapper(SbkBaseWrapper* pyObj, bool value); -LIBSHIBOKEN_API bool hasCppWrapper(SbkBaseWrapper* pyObj); +LIBSHIBOKEN_API void setValidCpp(SbkObject* pyObj, bool value); +LIBSHIBOKEN_API void setHasCppWrapper(SbkObject* pyObj, bool value); +LIBSHIBOKEN_API bool hasCppWrapper(SbkObject* pyObj); -LIBSHIBOKEN_API void getOwnership(PyObject* pyobj); -LIBSHIBOKEN_API void getOwnership(SbkBaseWrapper* pyobj); -LIBSHIBOKEN_API void releaseOwnership(PyObject* pyobj); -LIBSHIBOKEN_API void releaseOwnership(SbkBaseWrapper* pyobj); +LIBSHIBOKEN_API void getOwnership(PyObject* pyObj); +LIBSHIBOKEN_API void getOwnership(SbkObject* pyObj); +LIBSHIBOKEN_API void releaseOwnership(PyObject* pyObj); +LIBSHIBOKEN_API void releaseOwnership(SbkObject* pyObj); } // namespace Wrapper diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h index 1a72781d..34a3ea6d 100644 --- a/libshiboken/basewrapper_p.h +++ b/libshiboken/basewrapper_p.h @@ -27,7 +27,7 @@ #include #include -struct SbkBaseWrapper; +struct SbkObject; namespace Shiboken { @@ -35,11 +35,11 @@ namespace Shiboken * This mapping associates a method and argument of an wrapper object with the wrapper of * said argument when it needs the binding to help manage its reference counting. */ -typedef std::map > RefCountMap; +typedef std::map > RefCountMap; /// Linked list of SbkBaseWrapper pointers -typedef std::list ChildrenList; +typedef std::list ChildrenList; /// Struct used to store information about object parent and children. struct ParentInfo @@ -47,7 +47,7 @@ struct ParentInfo /// Default ctor. ParentInfo() : parent(0), hasWrapperRef(false) {} /// Pointer to parent object. - SbkBaseWrapper* parent; + SbkObject* parent; /// List of object children. ChildrenList children; /// has internal ref @@ -86,7 +86,7 @@ namespace Shiboken /** * Utility function uset to transform PyObject which suppot sequence protocol in a std::list **/ -std::list splitPyObject(PyObject* pyObj); +std::list splitPyObject(PyObject* pyObj); struct SbkBaseWrapperType; @@ -185,7 +185,7 @@ inline std::list getCppBaseClasses(PyTypeObject* baseType) * Decrements the reference counters of every object referred by self. * \param self the wrapper instance that keeps references to other objects. */ -void clearReferences(SbkBaseWrapper* self); +void clearReferences(SbkObject* self); } // namespace Shiboken diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index 5e9be699..e2d32d83 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -162,7 +162,7 @@ bool BindingManager::hasWrapper(const void* cptr) { return m_d->wrapperMapper.count(cptr); } -void BindingManager::registerWrapper(SbkBaseWrapper* pyobj, void* cptr) +void BindingManager::registerWrapper(SbkObject* pyobj, void* cptr) { SbkBaseWrapperType* instanceType = reinterpret_cast(pyobj->ob_type); @@ -184,7 +184,7 @@ void BindingManager::releaseWrapper(PyObject* wrapper) SbkBaseWrapperType* sbkType = reinterpret_cast(wrapper->ob_type); int numBases = sbkType->is_multicpp ? getNumberOfCppBaseClasses(wrapper->ob_type) : 1; - void** cptrs = reinterpret_cast(wrapper)->d->cptr; + void** cptrs = reinterpret_cast(wrapper)->d->cptr; for (int i = 0; i < numBases; ++i) { void* cptr = cptrs[i]; m_d->releaseWrapper(cptr); @@ -250,13 +250,13 @@ PyObject* BindingManager::getOverride(const void* cptr, const char* methodName) void BindingManager::invalidateWrapper(PyObject* pyobj) { - std::list objs = splitPyObject(pyobj); - std::list::const_iterator it = objs.begin(); + std::list objs = splitPyObject(pyobj); + std::list::const_iterator it = objs.begin(); for(; it != objs.end(); it++) invalidateWrapper(*it); } -void BindingManager::invalidateWrapper(SbkBaseWrapper* wrapper) +void BindingManager::invalidateWrapper(SbkObject* wrapper) { if (!wrapper || ((PyObject*)wrapper == Py_None) || !wrapper->d->validCppObject) return; @@ -302,10 +302,10 @@ void BindingManager::destroyWrapper(const void* cptr) { WrapperMap::iterator iter = m_d->wrapperMapper.find(cptr); if (iter != m_d->wrapperMapper.end()) - destroyWrapper(reinterpret_cast(iter->second)); + destroyWrapper(reinterpret_cast(iter->second)); } -void BindingManager::destroyWrapper(SbkBaseWrapper* wrapper) +void BindingManager::destroyWrapper(SbkObject* wrapper) { GilState gil; m_d->destroying = true; @@ -315,13 +315,13 @@ void BindingManager::destroyWrapper(SbkBaseWrapper* wrapper) void BindingManager::transferOwnershipToCpp(PyObject* wrapper) { - std::list objs = splitPyObject(wrapper); - std::list::const_iterator it = objs.begin(); + std::list objs = splitPyObject(wrapper); + std::list::const_iterator it = objs.begin(); for(; it != objs.end(); it++) transferOwnershipToCpp(*it); } -void BindingManager::transferOwnershipToCpp(SbkBaseWrapper* wrapper) +void BindingManager::transferOwnershipToCpp(SbkObject* wrapper) { if (wrapper->d->parentInfo) Shiboken::removeParent(wrapper); diff --git a/libshiboken/bindingmanager.h b/libshiboken/bindingmanager.h index b5bf43b6..31ed7981 100644 --- a/libshiboken/bindingmanager.h +++ b/libshiboken/bindingmanager.h @@ -27,7 +27,7 @@ #include #include "shibokenmacros.h" -struct SbkBaseWrapper; +struct SbkObject; namespace Shiboken { @@ -41,20 +41,20 @@ class LIBSHIBOKEN_API BindingManager bool hasWrapper(const void *cptr); - void registerWrapper(SbkBaseWrapper* pyobj, void* cptr); + void registerWrapper(SbkObject* pyobj, void* cptr); void releaseWrapper(PyObject* wrapper); PyObject* retrieveWrapper(const void* cptr); PyObject* getOverride(const void* cptr, const char* methodName); /// Invalidate the Python wrapper and removes the relations from C++ pointers to the Python wrapper. - void invalidateWrapper(SbkBaseWrapper* wrapper); + void invalidateWrapper(SbkObject* wrapper); /// Convenience method to call invalidateWrapper with a properly cast SbkBaseWrapper. void invalidateWrapper(PyObject* wrapper); /// Convenience method to invalidate the Python wrapper for a C++ wrapped object. Do nothing if C++ pointer has no Python wrapper. void invalidateWrapper(const void* cptr); /// Transfers the ownership of a Python wrapper to C++. - void transferOwnershipToCpp(SbkBaseWrapper* wrapper); + void transferOwnershipToCpp(SbkObject* wrapper); /// Convenience method to call transferOwnershipToCpp with a properly cast SbkBaseWrapper. void transferOwnershipToCpp(PyObject* wrapper); void addClassInheritance(SbkBaseWrapperType* parent, SbkBaseWrapperType* child); @@ -62,7 +62,7 @@ class LIBSHIBOKEN_API BindingManager /// Called by wrapper destructor void destroyWrapper(const void* cptr); - void destroyWrapper(SbkBaseWrapper* wrapper); + void destroyWrapper(SbkObject* wrapper); std::set getAllPyObjects(); private: ~BindingManager(); From cc58f2c2b7f80e8b749d3dd0577a9b18902e61bb Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 9 Nov 2010 18:16:38 -0200 Subject: [PATCH 110/564] Removed macros SbkBaseWrapper_instanceDict and SbkBaseWrapper_setInstanceDict --- generator/cppgenerator.cpp | 4 ++-- libshiboken/basewrapper.cpp | 6 ++--- libshiboken/basewrapper.h | 3 --- libshiboken/bindingmanager.cpp | 43 +++++++++++++++++----------------- libshiboken/bindingmanager.h | 8 +++---- libshiboken/conversions.h | 4 ++-- 6 files changed, 33 insertions(+), 35 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 4f4498ac..068616cf 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -3398,10 +3398,10 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, const AbstractMetaClass s << INDENT << "if (self) {" << endl; { Indentation indent(INDENT); - s << INDENT << "if (SbkBaseWrapper_instanceDict(self)) {" << endl; + s << INDENT << "if (reinterpret_cast(self)->ob_dict) {" << endl; { Indentation indent(INDENT); - s << INDENT << "PyObject* meth = PyDict_GetItem(SbkBaseWrapper_instanceDict(self), name);" << endl; + s << INDENT << "PyObject* meth = PyDict_GetItem(reinterpret_cast(self)->ob_dict, name);" << endl; s << INDENT << "if (meth) {" << endl; { Indentation indent(INDENT); diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index a1813350..199387be 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -388,9 +388,9 @@ void deallocWrapperWithPrivateDtor(PyObject* self) if (((SbkObject *)self)->weakreflist) PyObject_ClearWeakRefs(self); - BindingManager::instance().releaseWrapper(self); + BindingManager::instance().releaseWrapper(reinterpret_cast(self)); clearReferences(reinterpret_cast(self)); - Py_TYPE(reinterpret_cast(self))->tp_free(self); + self->ob_type->tp_free(self); } void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append) @@ -471,7 +471,7 @@ void deallocWrapper(PyObject* pyObj) if (sbkObj->weakreflist) PyObject_ClearWeakRefs(pyObj); - BindingManager::instance().releaseWrapper(pyObj); + BindingManager::instance().releaseWrapper(sbkObj); if (sbkObj->d->hasOwnership) { SbkBaseWrapperType* sbkType = reinterpret_cast(pyObj->ob_type); if (sbkType->is_multicpp) { diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 51ee7f8d..1393e1a2 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -175,9 +175,6 @@ LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctor #define SbkBaseWrapper_Check(op) PyObject_TypeCheck(op, (PyTypeObject*)&Shiboken::SbkBaseWrapper_Type) #define SbkBaseWrapper_CheckExact(op) ((op)->ob_type == &Shiboken::SbkBaseWrapper_Type) -#define SbkBaseWrapper_instanceDict(pyobj) (((SbkObject*)pyobj)->ob_dict) -#define SbkBaseWrapper_setInstanceDict(pyobj,d) (((SbkObject*)pyobj)->ob_dict = d) - LIBSHIBOKEN_API PyObject* SbkBaseWrapper_New(SbkBaseWrapperType* instanceType, void* cptr, diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index e2d32d83..e667f617 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -32,7 +32,7 @@ namespace Shiboken { -typedef google::dense_hash_map WrapperMap; +typedef google::dense_hash_map WrapperMap; class Graph { @@ -111,7 +111,7 @@ struct BindingManager::BindingManagerPrivate { BindingManagerPrivate() : destroying(false) {} void releaseWrapper(void* cptr); - void assignWrapper(PyObject* wrapper, const void* cptr); + void assignWrapper(SbkObject* wrapper, const void* cptr); }; @@ -122,7 +122,7 @@ void BindingManager::BindingManagerPrivate::releaseWrapper(void* cptr) wrapperMapper.erase(iter); } -void BindingManager::BindingManagerPrivate::assignWrapper(PyObject* wrapper, const void* cptr) +void BindingManager::BindingManagerPrivate::assignWrapper(SbkObject* wrapper, const void* cptr) { assert(cptr); WrapperMap::iterator iter = wrapperMapper.find(cptr); @@ -162,29 +162,29 @@ bool BindingManager::hasWrapper(const void* cptr) { return m_d->wrapperMapper.count(cptr); } -void BindingManager::registerWrapper(SbkObject* pyobj, void* cptr) +void BindingManager::registerWrapper(SbkObject* pyObj, void* cptr) { - SbkBaseWrapperType* instanceType = reinterpret_cast(pyobj->ob_type); + SbkBaseWrapperType* instanceType = reinterpret_cast(pyObj->ob_type); if (instanceType->mi_init && !instanceType->mi_offsets) instanceType->mi_offsets = instanceType->mi_init(cptr); - m_d->assignWrapper(reinterpret_cast(pyobj), cptr); + m_d->assignWrapper(pyObj, cptr); if (instanceType->mi_offsets) { int* offset = instanceType->mi_offsets; while (*offset != -1) { if (*offset > 0) - m_d->assignWrapper(reinterpret_cast(pyobj), reinterpret_cast((std::size_t) cptr + (*offset))); + m_d->assignWrapper(pyObj, reinterpret_cast((std::size_t) cptr + (*offset))); offset++; } } } -void BindingManager::releaseWrapper(PyObject* wrapper) +void BindingManager::releaseWrapper(SbkObject* sbkObj) { - SbkBaseWrapperType* sbkType = reinterpret_cast(wrapper->ob_type); - int numBases = sbkType->is_multicpp ? getNumberOfCppBaseClasses(wrapper->ob_type) : 1; + SbkBaseWrapperType* sbkType = reinterpret_cast(sbkObj->ob_type); + int numBases = sbkType->is_multicpp ? getNumberOfCppBaseClasses(sbkObj->ob_type) : 1; - void** cptrs = reinterpret_cast(wrapper)->d->cptr; + void** cptrs = reinterpret_cast(sbkObj)->d->cptr; for (int i = 0; i < numBases; ++i) { void* cptr = cptrs[i]; m_d->releaseWrapper(cptr); @@ -199,7 +199,7 @@ void BindingManager::releaseWrapper(PyObject* wrapper) } } -PyObject* BindingManager::retrieveWrapper(const void* cptr) +SbkObject* BindingManager::retrieveWrapper(const void* cptr) { WrapperMap::iterator iter = m_d->wrapperMapper.find(cptr); if (iter == m_d->wrapperMapper.end()) @@ -209,22 +209,23 @@ PyObject* BindingManager::retrieveWrapper(const void* cptr) PyObject* BindingManager::getOverride(const void* cptr, const char* methodName) { - PyObject* wrapper = retrieveWrapper(cptr); + SbkObject* wrapper = retrieveWrapper(cptr); if (!wrapper) return 0; - if (SbkBaseWrapper_instanceDict(wrapper)) { - PyObject* method = PyDict_GetItemString(SbkBaseWrapper_instanceDict(wrapper), methodName); + if (wrapper->ob_dict) { + PyObject* method = PyDict_GetItemString(wrapper->ob_dict, methodName); if (method) { - Py_INCREF(method); + Py_INCREF((PyObject*)method); return method; } } PyObject* pyMethodName = PyString_FromString(methodName); - PyObject* method = PyObject_GetAttr(wrapper, pyMethodName); + PyObject* method = PyObject_GetAttr((PyObject*)wrapper, pyMethodName); - if (method && PyMethod_Check(method) && reinterpret_cast(method)->im_self == wrapper) { + if (method && PyMethod_Check(method) + && reinterpret_cast(method)->im_self == reinterpret_cast(wrapper)) { PyObject* defaultMethod; PyObject* mro = wrapper->ob_type->tp_mro; @@ -288,7 +289,7 @@ void BindingManager::invalidateWrapper(SbkObject* wrapper) m_d->destroying = parentDestroying; } - releaseWrapper(reinterpret_cast(wrapper)); + releaseWrapper(wrapper); } void BindingManager::invalidateWrapper(const void* cptr) @@ -343,9 +344,9 @@ SbkBaseWrapperType* BindingManager::resolveType(void* cptr, Shiboken::SbkBaseWra return identifiedType ? identifiedType : type; } -std::set< PyObject* > BindingManager::getAllPyObjects() +std::set BindingManager::getAllPyObjects() { - std::set pyObjects; + std::set pyObjects; const WrapperMap& wrappersMap = m_d->wrapperMapper; WrapperMap::const_iterator it = wrappersMap.begin(); for (; it != wrappersMap.end(); ++it) diff --git a/libshiboken/bindingmanager.h b/libshiboken/bindingmanager.h index 31ed7981..910e6053 100644 --- a/libshiboken/bindingmanager.h +++ b/libshiboken/bindingmanager.h @@ -41,9 +41,9 @@ class LIBSHIBOKEN_API BindingManager bool hasWrapper(const void *cptr); - void registerWrapper(SbkObject* pyobj, void* cptr); - void releaseWrapper(PyObject* wrapper); - PyObject* retrieveWrapper(const void* cptr); + void registerWrapper(SbkObject* pyObj, void* cptr); + void releaseWrapper(SbkObject* wrapper); + SbkObject* retrieveWrapper(const void* cptr); PyObject* getOverride(const void* cptr, const char* methodName); /// Invalidate the Python wrapper and removes the relations from C++ pointers to the Python wrapper. @@ -63,7 +63,7 @@ class LIBSHIBOKEN_API BindingManager /// Called by wrapper destructor void destroyWrapper(const void* cptr); void destroyWrapper(SbkObject* wrapper); - std::set getAllPyObjects(); + std::set getAllPyObjects(); private: ~BindingManager(); // disable copy diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index b077e2f2..e443dad1 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -139,7 +139,7 @@ struct Converter { if (!cppobj) Py_RETURN_NONE; - PyObject* pyobj = BindingManager::instance().retrieveWrapper(cppobj); + PyObject* pyobj = reinterpret_cast(BindingManager::instance().retrieveWrapper(cppobj)); if (pyobj) Py_INCREF(pyobj); else @@ -263,7 +263,7 @@ struct ObjectTypeConverter { if (!cppobj) Py_RETURN_NONE; - PyObject* pyobj = BindingManager::instance().retrieveWrapper(cppobj); + PyObject* pyobj = reinterpret_cast(BindingManager::instance().retrieveWrapper(cppobj)); if (pyobj) Py_INCREF(pyobj); else From 7c099136210ee657a05d3544aacb54e50b4992e9 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 9 Nov 2010 18:42:02 -0200 Subject: [PATCH 111/564] setCppPointer and getCppPointer moved to namespace Shiboken::Wrapper --- generator/cppgenerator.cpp | 2 +- libshiboken/basewrapper.cpp | 50 +++++++++++++++++++------------------ libshiboken/basewrapper.h | 20 +++++++-------- libshiboken/conversions.h | 10 ++++---- 4 files changed, 42 insertions(+), 40 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 068616cf..d7b8afd0 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -915,7 +915,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun if (hasPythonConvertion) s << INDENT << "}" << endl; - s << INDENT << "if (PyErr_Occurred() || !Shiboken::setCppPointer(sbkSelf, Shiboken::SbkType<" << metaClass->qualifiedCppName() << " >(), cptr)) {" << endl; + s << INDENT << "if (PyErr_Occurred() || !Shiboken::Wrapper::setCppPointer(sbkSelf, Shiboken::SbkType<" << metaClass->qualifiedCppName() << " >(), cptr)) {" << endl; { Indentation indent(INDENT); s << INDENT << "delete cptr;" << endl; diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 199387be..255bee32 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -333,30 +333,6 @@ PyObject* SbkBaseWrapper_TpNew(PyTypeObject* subtype, PyObject*, PyObject*) return reinterpret_cast(self); } -void* getCppPointer(PyObject* wrapper, PyTypeObject* desiredType) -{ - PyTypeObject* type = wrapper->ob_type; - int idx = 0; - if (reinterpret_cast(type)->is_multicpp) - idx = getTypeIndexOnHierarchy(type, desiredType); - return reinterpret_cast(wrapper)->d->cptr[idx]; -} - -bool setCppPointer(SbkObject* wrapper, PyTypeObject* desiredType, void* cptr) -{ - int idx = 0; - if (reinterpret_cast(wrapper->ob_type)->is_multicpp) - idx = getTypeIndexOnHierarchy(wrapper->ob_type, desiredType); - - bool alreadyInitialized = wrapper->d->cptr[idx]; - if (alreadyInitialized) - PyErr_SetString(PyExc_RuntimeError, "You can't initialize an object twice!"); - else - wrapper->d->cptr[idx] = cptr; - - return !alreadyInitialized; -} - bool cppObjectIsInvalid(PyObject* wrapper) { if (!wrapper || wrapper == Py_None @@ -727,6 +703,32 @@ void releaseOwnership(PyObject* pyObj) setSequenceOwnership(pyObj, false); } +void* cppPointer(PyObject* pyObj, PyTypeObject* desiredType) +{ + assert(isShibokenType(pyObj)); + PyTypeObject* type = pyObj->ob_type; + int idx = 0; + if (reinterpret_cast(type)->is_multicpp) + idx = getTypeIndexOnHierarchy(type, desiredType); + return reinterpret_cast(pyObj)->d->cptr[idx]; +} + +bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr) +{ + int idx = 0; + if (reinterpret_cast(sbkObj->ob_type)->is_multicpp) + idx = getTypeIndexOnHierarchy(sbkObj->ob_type, desiredType); + + bool alreadyInitialized = sbkObj->d->cptr[idx]; + if (alreadyInitialized) + PyErr_SetString(PyExc_RuntimeError, "You can't initialize an object twice!"); + else + sbkObj->d->cptr[idx] = cptr; + + return !alreadyInitialized; +} + + } // namespace Wrapper } // namespace Shiboken diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 1393e1a2..bb76f7ba 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -145,16 +145,6 @@ inline bool isUserType(PyObject*& pyObj) return isShibokenType(pyObj) && reinterpret_cast(pyObj->ob_type)->is_user_type; } -/** -* Get the C++ pointer of type \p desiredType from a Python object. -*/ -LIBSHIBOKEN_API void* getCppPointer(PyObject* wrapper, PyTypeObject* desiredType); - -/** -* Set the C++ pointer of type \p desiredType of a Python object. -*/ -LIBSHIBOKEN_API bool setCppPointer(SbkObject* wrapper, PyTypeObject* desiredType, void* cptr); - /** * Get/Set Userdata in type class */ @@ -227,6 +217,16 @@ LIBSHIBOKEN_API void getOwnership(SbkObject* pyObj); LIBSHIBOKEN_API void releaseOwnership(PyObject* pyObj); LIBSHIBOKEN_API void releaseOwnership(SbkObject* pyObj); +/** + * Get the C++ pointer of type \p desiredType from a Python object. + */ +LIBSHIBOKEN_API void* cppPointer(PyObject* pyObj, PyTypeObject* desiredType); + +/** + * Set the C++ pointer of type \p desiredType of a Python object. + */ +LIBSHIBOKEN_API bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr); + } // namespace Wrapper } // namespace Shiboken diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index e443dad1..4cead343 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -150,7 +150,7 @@ struct Converter static T* toCpp(PyObject* pyobj) { if (Shiboken_TypeCheck(pyobj, T)) - return (T*) getCppPointer(pyobj, SbkType()); + return (T*) Wrapper::cppPointer(pyobj, SbkType()); else if (Converter::isConvertible(pyobj)) return CppObjectCopier::copy(Converter::toCpp(pyobj)); @@ -243,7 +243,7 @@ struct ValueTypeConverter } assert(false); } - return *reinterpret_cast(getCppPointer(pyobj, SbkType())); + return *reinterpret_cast(Wrapper::cppPointer(pyobj, SbkType())); } }; @@ -277,8 +277,8 @@ struct ObjectTypeConverter return 0; SbkBaseWrapperType* shiboType = reinterpret_cast(pyobj->ob_type); if (shiboType->mi_specialcast) - return (T*) shiboType->mi_specialcast(getCppPointer(pyobj, SbkType()), reinterpret_cast(SbkType())); - return (T*) getCppPointer(pyobj, SbkType()); + return (T*) shiboType->mi_specialcast(Wrapper::cppPointer(pyobj, SbkType()), reinterpret_cast(SbkType())); + return (T*) Wrapper::cppPointer(pyobj, SbkType()); } }; @@ -587,7 +587,7 @@ struct StdListConverter static StdList toCpp(PyObject* pyobj) { if (PyObject_TypeCheck(pyobj, SbkType())) - return *reinterpret_cast(getCppPointer(pyobj, SbkType())); + return *reinterpret_cast(Wrapper::cppPointer(pyobj, SbkType())); StdList result; for (int i = 0; i < PySequence_Size(pyobj); i++) { From 3bb009fe0eea00c2d8e294fd45e0a861c9bf19f8 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 9 Nov 2010 18:52:40 -0200 Subject: [PATCH 112/564] Replace Shiboken::cppObjectIsInvalid by Shiboken::Wraper::isValid --- generator/cppgenerator.cpp | 10 +++++----- libshiboken/basewrapper.cpp | 21 ++++++++++----------- libshiboken/basewrapper.h | 7 ++++--- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index d7b8afd0..6ff3e88b 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -1420,7 +1420,7 @@ void CppGenerator::writeErrorSection(QTextStream& s, OverloadData& overloadData) void CppGenerator::writeInvalidCppObjectCheck(QTextStream& s, QString pyArgName, const TypeEntry* type) { - s << INDENT << "if (Shiboken::cppObjectIsInvalid(" << pyArgName << "))" << endl; + s << INDENT << "if (!Shiboken::Wrapper::isValid(" << pyArgName << "))" << endl; Indentation indent(INDENT); s << INDENT << "return " << m_currentErrorCode << ';' << endl; } @@ -2652,7 +2652,7 @@ void CppGenerator::writeCopyFunction(QTextStream& s, const AbstractMetaClass *me s << "static PyObject *" << className << "___copy__(PyObject *self)" << endl; s << "{" << endl; s << INDENT << metaClass->qualifiedCppName() << "* " CPP_SELF_VAR " = 0;" << endl; - s << INDENT << "if (Shiboken::cppObjectIsInvalid(self))" << endl; + s << INDENT << "if (!Shiboken::Wrapper::isValid(self))" << endl; { Indentation indent(INDENT); s << INDENT << "return 0;" << endl; @@ -3860,7 +3860,7 @@ void CppGenerator::writeStdListWrapperMethods(QTextStream& s, const AbstractMeta { //len s << "Py_ssize_t " << cpythonBaseName(metaClass->typeEntry()) << "__len__" << "(PyObject* self)" << endl << '{' << endl; - s << INDENT << "if (Shiboken::cppObjectIsInvalid(self))" << endl; + s << INDENT << "if (!Shiboken::Wrapper::isValid(self))" << endl; s << INDENT << INDENT << "return 0;" << endl << endl; s << INDENT << metaClass->qualifiedCppName() << " &cppSelf = Shiboken::Converter<" << metaClass->qualifiedCppName() <<"& >::toCpp(self);" << endl; s << INDENT << "return cppSelf.size();" << endl; @@ -3868,7 +3868,7 @@ void CppGenerator::writeStdListWrapperMethods(QTextStream& s, const AbstractMeta //getitem s << "PyObject* " << cpythonBaseName(metaClass->typeEntry()) << "__getitem__" << "(PyObject* self, Py_ssize_t _i)" << endl << '{' << endl; - s << INDENT << "if (Shiboken::cppObjectIsInvalid(self))" << endl; + s << INDENT << "if (!Shiboken::Wrapper::isValid(self))" << endl; s << INDENT << INDENT << "return 0;" << endl << endl; s << INDENT << metaClass->qualifiedCppName() << " &cppSelf = Shiboken::Converter<" << metaClass->qualifiedCppName() <<"& >::toCpp(self);" << endl; s << INDENT << "if (_i < 0 || _i >= (Py_ssize_t) cppSelf.size()) {" << endl; @@ -3881,7 +3881,7 @@ void CppGenerator::writeStdListWrapperMethods(QTextStream& s, const AbstractMeta //setitem s << "int " << cpythonBaseName(metaClass->typeEntry()) << "__setitem__" << "(PyObject* self, Py_ssize_t _i, PyObject* _value)" << endl << '{' << endl; - s << INDENT << "if (Shiboken::cppObjectIsInvalid(self))" << endl; + s << INDENT << "if (!Shiboken::Wrapper::isValid(self))" << endl; s << INDENT << INDENT << "return -1;" << endl; s << INDENT << metaClass->qualifiedCppName() << " &cppSelf = Shiboken::Converter<" << metaClass->qualifiedCppName() <<"& >::toCpp(self);" << endl; s << INDENT << "if (_i < 0 || _i >= (Py_ssize_t) cppSelf.size()) {" << endl; diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 255bee32..7aa5ed0e 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -333,17 +333,6 @@ PyObject* SbkBaseWrapper_TpNew(PyTypeObject* subtype, PyObject*, PyObject*) return reinterpret_cast(self); } -bool cppObjectIsInvalid(PyObject* wrapper) -{ - if (!wrapper || wrapper == Py_None - || wrapper->ob_type->ob_type != &Shiboken::SbkBaseWrapperType_Type - || ((SbkObject*)wrapper)->d->validCppObject) { - return false; - } - PyErr_SetString(PyExc_RuntimeError, "Internal C++ object already deleted."); - return true; -} - void setTypeUserData(SbkObject* wrapper, void *user_data, DeleteUserDataFunc d_func) { SbkBaseWrapperType* ob_type = reinterpret_cast(wrapper->ob_type); @@ -728,6 +717,16 @@ bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr) return !alreadyInitialized; } +bool isValid(PyObject* pyObj) +{ + if (!pyObj || pyObj == Py_None + || pyObj->ob_type->ob_type != &Shiboken::SbkBaseWrapperType_Type + || ((SbkObject*)pyObj)->d->validCppObject) { + return true; + } + PyErr_Format(PyExc_RuntimeError, "Internal C++ object (%s) already deleted.", pyObj->ob_type->tp_name); + return false; +} } // namespace Wrapper diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index bb76f7ba..d8511dd8 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -189,9 +189,6 @@ SbkBaseWrapper_TpNew(PyTypeObject* subtype, PyObject*, PyObject*); */ LIBSHIBOKEN_API void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append=false); -/// Returns true and sets a Python RuntimeError if the Python wrapper is not marked as valid. -LIBSHIBOKEN_API bool cppObjectIsInvalid(PyObject* wrapper); - /// Dealloc the python object \p pyObj and the C++ object represented by it. LIBSHIBOKEN_API void deallocWrapper(PyObject* pyObj); @@ -227,6 +224,10 @@ LIBSHIBOKEN_API void* cppPointer(PyObject* pyObj, PyTypeObject* desiredType); */ LIBSHIBOKEN_API bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr); +/// Returns false and sets a Python RuntimeError if the Python wrapper is not marked as valid. +LIBSHIBOKEN_API bool isValid(PyObject* wrapper); + + } // namespace Wrapper } // namespace Shiboken From b9ad071fcb2a1fa2f0191815ed7b1f7573e8f01a Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 9 Nov 2010 18:57:02 -0200 Subject: [PATCH 113/564] Fix camel case of decRefPyObjectlist --- libshiboken/basewrapper.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 7aa5ed0e..5c0c3c21 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -36,7 +36,7 @@ namespace Shiboken static void SbkBaseWrapperType_dealloc(PyObject* pyObj); static PyObject* SbkBaseWrapperType_TpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds); static void incRefPyObject(PyObject* pyObj); -static void decRefPyObjectlist(const std::list &pyObj); +static void decRefPyObjectList(const std::list &pyObj); extern "C" { @@ -372,7 +372,7 @@ void keepReference(SbkObject* self, const char* key, PyObject* referredObject, b RefCountMap::iterator iter = refCountMap.find(key); if (!append && (iter != refCountMap.end())) { - decRefPyObjectlist(iter->second); + decRefPyObjectList(iter->second); refCountMap.erase(iter); } @@ -393,7 +393,7 @@ void clearReferences(SbkObject* self) RefCountMap& refCountMap = *(self->d->referredObjects); RefCountMap::iterator iter; for (iter = refCountMap.begin(); iter != refCountMap.end(); ++iter) - decRefPyObjectlist(iter->second); + decRefPyObjectList(iter->second); delete self->d->referredObjects; self->d->referredObjects = 0; } @@ -633,7 +633,7 @@ static void incRefPyObject(PyObject* pyObj) } } -static void decRefPyObjectlist(const std::list &lst) +static void decRefPyObjectList(const std::list& lst) { std::list::const_iterator iter = lst.begin(); while(iter != lst.end()) { From 9016e6ef09c19406d2e57066966eae4d54010728 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 10 Nov 2010 11:42:46 -0200 Subject: [PATCH 114/564] SbkBaseWrapperType and some other functions used by Python C-API moved outside C++ namespaces. --- generator/cppgenerator.cpp | 16 +- libshiboken/basewrapper.cpp | 266 +++++++++++----------- libshiboken/basewrapper.h | 43 ++-- libshiboken/basewrapper_p.h | 13 +- libshiboken/bindingmanager.cpp | 4 +- libshiboken/bindingmanager.h | 3 +- libshiboken/conversions.h | 2 +- libshiboken/typeresolver.h | 4 +- tests/samplebinding/typesystem_sample.xml | 2 +- 9 files changed, 176 insertions(+), 177 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 6ff3e88b..aee295f0 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2274,7 +2274,7 @@ void CppGenerator::writeExtendedToCppFunction(QTextStream& s, const TypeEntry* e void CppGenerator::writeExtendedConverterInitialization(QTextStream& s, const TypeEntry* externalType, const QList& conversions) { s << INDENT << "// Extended implicit conversions for " << externalType->targetLangPackage() << '.' << externalType->name() << endl; - s << INDENT << "shiboType = reinterpret_cast("; + s << INDENT << "shiboType = reinterpret_cast("; s << cppApiVariableName(externalType->targetLangPackage()) << '['; s << getTypeIndexVariableName(externalType) << "]);" << endl; s << INDENT << "shiboType->ext_isconvertible = " << extendedIsConvertibleFunctionName(externalType) << ';' << endl; @@ -2341,12 +2341,12 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* tp_as_sequence = QString("&Py%1_as_sequence").arg(cppClassName); if (!metaClass->baseClass()) - baseClassName = "reinterpret_cast(&Shiboken::SbkBaseWrapper_Type)"; + baseClassName = "reinterpret_cast(&SbkBaseWrapper_Type)"; if (metaClass->isNamespace() || metaClass->hasPrivateDestructor()) { tp_flags = "Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES"; tp_dealloc = metaClass->hasPrivateDestructor() ? - "Shiboken::deallocWrapperWithPrivateDtor" : "0"; + "SbkDeallocWrapperWithPrivateDtor" : "0"; tp_init = "0"; } else { if (onlyPrivCtor) @@ -2359,7 +2359,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* deallocClassName = wrapperName(metaClass); else deallocClassName = cppClassName; - tp_dealloc = "&Shiboken::deallocWrapper"; + tp_dealloc = "&SbkDeallocWrapper"; QString dtorClassName = metaClass->qualifiedCppName(); #ifdef AVOID_PROTECTED_HACK @@ -2383,7 +2383,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* if (metaClass->hasPrivateDestructor() || onlyPrivCtor) tp_new = "0"; else - tp_new = "Shiboken::SbkBaseWrapper_TpNew"; + tp_new = "SbkBaseWrapper_TpNew"; QString tp_richcompare = QString('0'); if (metaClass->hasComparisonOperatorOverload()) @@ -2426,7 +2426,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* s << "// Class Definition -----------------------------------------------" << endl; s << "extern \"C\" {" << endl; s << "static SbkBaseWrapperType " << className + "_Type" << " = { { {" << endl; - s << INDENT << "PyObject_HEAD_INIT(&Shiboken::SbkBaseWrapperType_Type)" << endl; + s << INDENT << "PyObject_HEAD_INIT(&SbkBaseWrapperType_Type)" << endl; s << INDENT << "/*ob_size*/ 0," << endl; s << INDENT << "/*tp_name*/ \"" << metaClass->fullName() << "\"," << endl; s << INDENT << "/*tp_basicsize*/ sizeof(SbkObject)," << endl; @@ -3359,7 +3359,7 @@ void CppGenerator::writeTypeDiscoveryFunction(QTextStream& s, const AbstractMeta if (ancestor->baseClass()) continue; if (ancestor->isPolymorphic()) { - s << INDENT << "if (instanceType == reinterpret_cast(Shiboken::SbkType<" + s << INDENT << "if (instanceType == reinterpret_cast(Shiboken::SbkType<" << ancestor->qualifiedCppName() << " >()) && dynamic_cast<" << metaClass->qualifiedCppName() << "*>(reinterpret_cast<"<< ancestor->qualifiedCppName() << "*>(cptr)))" << endl; Indentation indent(INDENT); @@ -3680,7 +3680,7 @@ void CppGenerator::finishGeneration() if (!extendedConverters.isEmpty()) { s << INDENT << "// Initialize extended Converters" << endl; - s << INDENT << "Shiboken::SbkBaseWrapperType* shiboType;" << endl << endl; + s << INDENT << "SbkBaseWrapperType* shiboType;" << endl << endl; } foreach (const TypeEntry* externalType, extendedConverters.keys()) { writeExtendedConverterInitialization(s, externalType, extendedConverters[externalType]); diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 5c0c3c21..5de9024e 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -30,16 +30,11 @@ #include #include -namespace Shiboken +extern "C" { static void SbkBaseWrapperType_dealloc(PyObject* pyObj); static PyObject* SbkBaseWrapperType_TpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds); -static void incRefPyObject(PyObject* pyObj); -static void decRefPyObjectList(const std::list &pyObj); - -extern "C" -{ PyTypeObject SbkBaseWrapperType_Type = { PyObject_HEAD_INIT(0) @@ -111,7 +106,7 @@ SbkBaseWrapperType SbkBaseWrapper_Type = { { { /*tp_name*/ "Shiboken.BaseWrapper", /*tp_basicsize*/ sizeof(SbkObject), /*tp_itemsize*/ 0, - /*tp_dealloc*/ deallocWrapperWithPrivateDtor, + /*tp_dealloc*/ SbkDeallocWrapperWithPrivateDtor, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, @@ -161,8 +156,105 @@ SbkBaseWrapperType SbkBaseWrapper_Type = { { { /*ext_tocpp*/ 0 }; + +void SbkDeallocWrapper(PyObject* pyObj) +{ + SbkObject* sbkObj = reinterpret_cast(pyObj); + if (sbkObj->weakreflist) + PyObject_ClearWeakRefs(pyObj); + + Shiboken::BindingManager::instance().releaseWrapper(sbkObj); + if (sbkObj->d->hasOwnership) { + SbkBaseWrapperType* sbkType = reinterpret_cast(pyObj->ob_type); + if (sbkType->is_multicpp) { + Shiboken::DtorCallerVisitor visitor(sbkObj); + Shiboken::walkThroughClassHierarchy(pyObj->ob_type, &visitor); + } else { + sbkType->cpp_dtor(sbkObj->d->cptr[0]); + } + } + + if (sbkObj->d->parentInfo) + Shiboken::destroyParentInfo(sbkObj); + + Shiboken::clearReferences(sbkObj); + + Py_XDECREF(sbkObj->ob_dict); + delete[] sbkObj->d->cptr; + sbkObj->d->cptr = 0; + delete sbkObj->d; + Py_TYPE(pyObj)->tp_free(pyObj); +} + +void SbkDeallocWrapperWithPrivateDtor(PyObject* self) +{ + if (((SbkObject *)self)->weakreflist) + PyObject_ClearWeakRefs(self); + + Shiboken::BindingManager::instance().releaseWrapper(reinterpret_cast(self)); + Shiboken::clearReferences(reinterpret_cast(self)); + self->ob_type->tp_free(self); +} + +void SbkBaseWrapperType_dealloc(PyObject* pyObj) +{ + SbkBaseWrapperType *sbkType = reinterpret_cast(pyObj->ob_type); + + if(sbkType->user_data && sbkType->d_func) { + sbkType->d_func(sbkType->user_data); + sbkType->user_data = 0; + } +} + +PyObject* SbkBaseWrapperType_TpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds) +{ + // The meta type creates a new type when the Python programmer extends a wrapped C++ class. + SbkBaseWrapperType* newType = reinterpret_cast(PyType_Type.tp_new(metatype, args, kwds)); + + if (!newType) + return 0; + + std::list bases = Shiboken::getCppBaseClasses(reinterpret_cast(newType)); + if (bases.size() == 1) { + SbkBaseWrapperType* parentType = bases.front(); + newType->mi_offsets = parentType->mi_offsets; + newType->mi_init = parentType->mi_init; + newType->mi_specialcast = parentType->mi_specialcast; + newType->ext_isconvertible = parentType->ext_isconvertible; + newType->ext_tocpp = parentType->ext_tocpp; + newType->type_discovery = parentType->type_discovery; + newType->obj_copier = parentType->obj_copier; + newType->cpp_dtor = parentType->cpp_dtor; + newType->is_multicpp = 0; + } else { + newType->mi_offsets = 0; + newType->mi_init = 0; + newType->mi_specialcast = 0; + newType->ext_isconvertible = 0; + newType->ext_tocpp = 0; + newType->type_discovery = 0; + newType->obj_copier = 0; + newType->cpp_dtor = 0; + newType->is_multicpp = 1; + } + if (bases.size() == 1) + newType->original_name = bases.front()->original_name; + else + newType->original_name = "object"; + newType->user_data = 0; + newType->d_func = 0; + newType->is_user_type = 1; + return reinterpret_cast(newType); +} + } //extern "C" +namespace Shiboken +{ + +static void incRefPyObject(PyObject* pyObj); +static void decRefPyObjectList(const std::list &pyObj); + void removeParent(SbkObject* child) { ParentInfo* pInfo = child->d->parentInfo; @@ -268,31 +360,6 @@ void destroyParentInfo(SbkObject* obj, bool removeFromParent) _destroyParentInfo(obj, removeFromParent); } -PyObject* SbkBaseWrapper_New(SbkBaseWrapperType* instanceType, - void* cptr, - bool hasOwnership, - bool isExactType, const char* typeName) -{ - // Try to find the exact type of cptr. - if (!isExactType) { - TypeResolver* tr = 0; - if (typeName) { - tr = TypeResolver::get(typeName); - if (tr) - instanceType = reinterpret_cast(tr->pythonType()); - } - if (!tr) - instanceType = BindingManager::instance().resolveType(cptr, instanceType); - } - - SbkObject* self = reinterpret_cast(SbkBaseWrapper_TpNew(reinterpret_cast(instanceType), 0, 0)); - self->d->cptr[0] = cptr; - self->d->hasOwnership = hasOwnership; - self->d->validCppObject = 1; - BindingManager::instance().registerWrapper(self, cptr); - return reinterpret_cast(self); -} - void walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visitor) { PyObject* bases = currentType->tp_bases; @@ -300,7 +367,7 @@ void walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visi for (int i = 0; i < numBases; ++i) { PyTypeObject* type = reinterpret_cast(PyTuple_GET_ITEM(bases, i)); - if (type->ob_type != &Shiboken::SbkBaseWrapperType_Type) { + if (type->ob_type != &SbkBaseWrapperType_Type) { continue; } else { SbkBaseWrapperType* sbkType = reinterpret_cast(type); @@ -348,16 +415,6 @@ void* getTypeUserData(SbkObject* wrapper) return reinterpret_cast(wrapper->ob_type)->user_data; } -void deallocWrapperWithPrivateDtor(PyObject* self) -{ - if (((SbkObject *)self)->weakreflist) - PyObject_ClearWeakRefs(self); - - BindingManager::instance().releaseWrapper(reinterpret_cast(self)); - clearReferences(reinterpret_cast(self)); - self->ob_type->tp_free(self); -} - void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append) { @@ -416,99 +473,10 @@ bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr) // Wrapper metatype and base type ---------------------------------------------------------- -class DtorCallerVisitor : public HierarchyVisitor -{ -public: - DtorCallerVisitor(SbkObject* pyObj) : m_count(0), m_pyObj(pyObj) {} - virtual void visit(SbkBaseWrapperType* node) - { - node->cpp_dtor(m_pyObj->d->cptr[m_count]); - m_count++; - } -private: - int m_count; - SbkObject* m_pyObj; -}; - -void deallocWrapper(PyObject* pyObj) +void DtorCallerVisitor::visit(SbkBaseWrapperType* node) { - SbkObject* sbkObj = reinterpret_cast(pyObj); - if (sbkObj->weakreflist) - PyObject_ClearWeakRefs(pyObj); - - BindingManager::instance().releaseWrapper(sbkObj); - if (sbkObj->d->hasOwnership) { - SbkBaseWrapperType* sbkType = reinterpret_cast(pyObj->ob_type); - if (sbkType->is_multicpp) { - DtorCallerVisitor visitor(sbkObj); - walkThroughClassHierarchy(pyObj->ob_type, &visitor); - } else { - sbkType->cpp_dtor(sbkObj->d->cptr[0]); - } - } - - if (sbkObj->d->parentInfo) - destroyParentInfo(sbkObj); - - clearReferences(sbkObj); - - Py_XDECREF(sbkObj->ob_dict); - delete[] sbkObj->d->cptr; - sbkObj->d->cptr = 0; - delete sbkObj->d; - Py_TYPE(pyObj)->tp_free(pyObj); - -} - -void SbkBaseWrapperType_dealloc(PyObject* pyObj) -{ - SbkBaseWrapperType *sbkType = reinterpret_cast(pyObj->ob_type); - - if(sbkType->user_data && sbkType->d_func) { - sbkType->d_func(sbkType->user_data); - sbkType->user_data = 0; - } -} - -PyObject* SbkBaseWrapperType_TpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds) -{ - // The meta type creates a new type when the Python programmer extends a wrapped C++ class. - SbkBaseWrapperType* newType = reinterpret_cast(PyType_Type.tp_new(metatype, args, kwds)); - - if (!newType) - return 0; - - std::list bases = getCppBaseClasses(reinterpret_cast(newType)); - if (bases.size() == 1) { - SbkBaseWrapperType* parentType = bases.front(); - newType->mi_offsets = parentType->mi_offsets; - newType->mi_init = parentType->mi_init; - newType->mi_specialcast = parentType->mi_specialcast; - newType->ext_isconvertible = parentType->ext_isconvertible; - newType->ext_tocpp = parentType->ext_tocpp; - newType->type_discovery = parentType->type_discovery; - newType->obj_copier = parentType->obj_copier; - newType->cpp_dtor = parentType->cpp_dtor; - newType->is_multicpp = 0; - } else { - newType->mi_offsets = 0; - newType->mi_init = 0; - newType->mi_specialcast = 0; - newType->ext_isconvertible = 0; - newType->ext_tocpp = 0; - newType->type_discovery = 0; - newType->obj_copier = 0; - newType->cpp_dtor = 0; - newType->is_multicpp = 1; - } - if (bases.size() == 1) - newType->original_name = bases.front()->original_name; - else - newType->original_name = "object"; - newType->user_data = 0; - newType->d_func = 0; - newType->is_user_type = 1; - return reinterpret_cast(newType); + node->cpp_dtor(m_pyObj->d->cptr[m_count]); + m_count++; } void initShiboken() @@ -720,7 +688,7 @@ bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr) bool isValid(PyObject* pyObj) { if (!pyObj || pyObj == Py_None - || pyObj->ob_type->ob_type != &Shiboken::SbkBaseWrapperType_Type + || pyObj->ob_type->ob_type != &SbkBaseWrapperType_Type || ((SbkObject*)pyObj)->d->validCppObject) { return true; } @@ -728,6 +696,32 @@ bool isValid(PyObject* pyObj) return false; } +PyObject* newObject(SbkBaseWrapperType* instanceType, + void* cptr, + bool hasOwnership, + bool isExactType, + const char* typeName) +{ + // Try to find the exact type of cptr. + if (!isExactType) { + TypeResolver* tr = 0; + if (typeName) { + tr = TypeResolver::get(typeName); + if (tr) + instanceType = reinterpret_cast(tr->pythonType()); + } + if (!tr) + instanceType = BindingManager::instance().resolveType(cptr, instanceType); + } + + SbkObject* self = reinterpret_cast(SbkBaseWrapper_TpNew(reinterpret_cast(instanceType), 0, 0)); + self->d->cptr[0] = cptr; + self->d->hasOwnership = hasOwnership; + self->d->validCppObject = 1; + BindingManager::instance().registerWrapper(self, cptr); + return reinterpret_cast(self); +} + } // namespace Wrapper } // namespace Shiboken diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index d8511dd8..9702992a 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -46,22 +46,21 @@ struct LIBSHIBOKEN_API SbkObject SbkBaseWrapperPrivate* d; }; -} -namespace Shiboken -{ +/// Dealloc the python object \p pyObj and the C++ object represented by it. +LIBSHIBOKEN_API void SbkDeallocWrapper(PyObject* pyObj); +LIBSHIBOKEN_API void SbkDeallocWrapperWithPrivateDtor(PyObject* self); + +struct SbkBaseWrapperType; -extern "C" -{ /// Function signature for the multiple inheritance information initializers that should be provided by classes with multiple inheritance. typedef int* (*MultipleInheritanceInitFunction)(const void*); -struct SbkBaseWrapperType; /** -* Special cast function is used to correctly cast an object when it's -* part of a multiple inheritance hierarchy. -* The implementation of this function is auto generated by the generator and you don't need to care about it. -*/ + * Special cast function is used to correctly cast an object when it's + * part of a multiple inheritance hierarchy. + * The implementation of this function is auto generated by the generator and you don't need to care about it. + */ typedef void* (*SpecialCastFunction)(void*, SbkBaseWrapperType*); typedef void* (*ObjectCopierFunction)(const void*); typedef SbkBaseWrapperType* (*TypeDiscoveryFunc)(void*, SbkBaseWrapperType*); @@ -104,6 +103,9 @@ struct LIBSHIBOKEN_API SbkBaseWrapperType } // extern "C" +namespace Shiboken +{ + /** * Init shiboken library. */ @@ -162,15 +164,8 @@ LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctor */ #define Shiboken_TypeCheck(pyobj, type) (PyObject_TypeCheck(pyobj, SbkType())) -#define SbkBaseWrapper_Check(op) PyObject_TypeCheck(op, (PyTypeObject*)&Shiboken::SbkBaseWrapper_Type) -#define SbkBaseWrapper_CheckExact(op) ((op)->ob_type == &Shiboken::SbkBaseWrapper_Type) - -LIBSHIBOKEN_API PyObject* -SbkBaseWrapper_New(SbkBaseWrapperType* instanceType, - void* cptr, - bool hasOwnership = true, - bool isExactType = false, - const char* typeName = 0); +#define SbkBaseWrapper_Check(op) PyObject_TypeCheck(op, (PyTypeObject*)&SbkBaseWrapper_Type) +#define SbkBaseWrapper_CheckExact(op) ((op)->ob_type == &SbkBaseWrapper_Type) LIBSHIBOKEN_API PyObject* SbkBaseWrapper_TpNew(PyTypeObject* subtype, PyObject*, PyObject*); @@ -189,9 +184,6 @@ SbkBaseWrapper_TpNew(PyTypeObject* subtype, PyObject*, PyObject*); */ LIBSHIBOKEN_API void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append=false); -/// Dealloc the python object \p pyObj and the C++ object represented by it. -LIBSHIBOKEN_API void deallocWrapper(PyObject* pyObj); - /// Delete the class T allocated on \p cptr. template void callCppDestructor(void* cptr) @@ -199,12 +191,17 @@ void callCppDestructor(void* cptr) delete reinterpret_cast(cptr); } -LIBSHIBOKEN_API void deallocWrapperWithPrivateDtor(PyObject* self); LIBSHIBOKEN_API bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr); LIBSHIBOKEN_API void setErrorAboutWrongArguments(PyObject* args, const char* funcName, const char** cppOverloads); namespace Wrapper { +LIBSHIBOKEN_API PyObject* newObject(SbkBaseWrapperType* instanceType, + void* cptr, + bool hasOwnership = true, + bool isExactType = false, + const char* typeName = 0); + LIBSHIBOKEN_API void setValidCpp(SbkObject* pyObj, bool value); LIBSHIBOKEN_API void setHasCppWrapper(SbkObject* pyObj, bool value); LIBSHIBOKEN_API bool hasCppWrapper(SbkObject* pyObj); diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h index 34a3ea6d..6b8b9ab3 100644 --- a/libshiboken/basewrapper_p.h +++ b/libshiboken/basewrapper_p.h @@ -28,6 +28,7 @@ #include struct SbkObject; +struct SbkBaseWrapperType; namespace Shiboken { @@ -88,8 +89,6 @@ namespace Shiboken **/ std::list splitPyObject(PyObject* pyObj); -struct SbkBaseWrapperType; - /** * Visitor class used by walkOnClassHierarchy function. */ @@ -152,6 +151,16 @@ class GetIndexVisitor : public HierarchyVisitor PyTypeObject* m_desiredType; }; +class DtorCallerVisitor : public HierarchyVisitor +{ +public: + DtorCallerVisitor(SbkObject* pyObj) : m_count(0), m_pyObj(pyObj) {} + void visit(SbkBaseWrapperType* node); +private: + int m_count; + SbkObject* m_pyObj; +}; + /// \internal Internal function used to walk on classes inheritance trees. /** * Walk on class hierarchy using a DFS algorithm. diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index e667f617..5e0cbf3d 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -333,12 +333,12 @@ void BindingManager::transferOwnershipToCpp(SbkObject* wrapper) invalidateWrapper(wrapper); } -void BindingManager::addClassInheritance(Shiboken::SbkBaseWrapperType* parent, Shiboken::SbkBaseWrapperType* child) +void BindingManager::addClassInheritance(SbkBaseWrapperType* parent, SbkBaseWrapperType* child) { m_d->classHierarchy.addEdge(parent, child); } -SbkBaseWrapperType* BindingManager::resolveType(void* cptr, Shiboken::SbkBaseWrapperType* type) +SbkBaseWrapperType* BindingManager::resolveType(void* cptr, SbkBaseWrapperType* type) { SbkBaseWrapperType* identifiedType = m_d->classHierarchy.identifyType(cptr, type, type); return identifiedType ? identifiedType : type; diff --git a/libshiboken/bindingmanager.h b/libshiboken/bindingmanager.h index 910e6053..8a6607fd 100644 --- a/libshiboken/bindingmanager.h +++ b/libshiboken/bindingmanager.h @@ -28,12 +28,11 @@ #include "shibokenmacros.h" struct SbkObject; +struct SbkBaseWrapperType; namespace Shiboken { -struct SbkBaseWrapperType; - class LIBSHIBOKEN_API BindingManager { public: diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index 4cead343..a590ea19 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -113,7 +113,7 @@ inline PyObject* createWrapper(const T* cppobj, bool hasOwnership = false, bool const char* typeName = 0; if (!isExactType) typeName = typeid(*const_cast(cppobj)).name(); - return SbkBaseWrapper_New(reinterpret_cast(SbkType()), + return Wrapper::newObject(reinterpret_cast(SbkType()), const_cast(cppobj), hasOwnership, isExactType, typeName); } diff --git a/libshiboken/typeresolver.h b/libshiboken/typeresolver.h index b11678e2..4e23b970 100644 --- a/libshiboken/typeresolver.h +++ b/libshiboken/typeresolver.h @@ -26,11 +26,11 @@ #include "shibokenmacros.h" #include "conversions.h" +class SbkBaseWrapperType; + namespace Shiboken { -class SbkBaseWrapperType; - /* To C++ convertion functions. */ template inline void* pythonToValueType(PyObject* pyobj, void** data, bool alloc) diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index ff367f4c..3285da13 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -1176,7 +1176,7 @@ %RETURN_TYPE %0 = %TYPE::%FUNCTION_NAME(); - %PYARG_0 = SbkBaseWrapper_New(&SbkBaseWrapper_Type, %0, false, false); + %PYARG_0 = Shiboken::Wrapper::newObject(&SbkBaseWrapper_Type, %0, false, false); From 0316703e8960c6b548e38ad243bdb4fd155b2460 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 10 Nov 2010 13:48:01 -0200 Subject: [PATCH 115/564] SbkBaseWrapper_TpNew renamed to SbkObjectTpNew, now using C linkage and moved outside C++ namespace. --- generator/cppgenerator.cpp | 2 +- libshiboken/basewrapper.cpp | 41 +++++++++++++++++++------------------ libshiboken/basewrapper.h | 5 ++--- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index aee295f0..3936d03f 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2383,7 +2383,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* if (metaClass->hasPrivateDestructor() || onlyPrivCtor) tp_new = "0"; else - tp_new = "SbkBaseWrapper_TpNew"; + tp_new = "SbkObjectTpNew"; QString tp_richcompare = QString('0'); if (metaClass->hasComparisonOperatorOverload()) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 5de9024e..3337a4d2 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -247,6 +247,26 @@ PyObject* SbkBaseWrapperType_TpNew(PyTypeObject* metatype, PyObject* args, PyObj return reinterpret_cast(newType); } +PyObject* SbkObjectTpNew(PyTypeObject* subtype, PyObject*, PyObject*) +{ + SbkObject* self = reinterpret_cast(subtype->tp_alloc(subtype, 0)); + self->d = new SbkBaseWrapperPrivate; + + SbkBaseWrapperType* sbkType = reinterpret_cast(subtype); + int numBases = sbkType->is_multicpp ? Shiboken::getNumberOfCppBaseClasses(subtype) : 1; + self->d->cptr = new void*[numBases]; + std::memset(self->d->cptr, 0, sizeof(void*)*numBases); + self->d->hasOwnership = 1; + self->d->containsCppWrapper = 0; + self->d->validCppObject = 0; + self->d->parentInfo = 0; + self->ob_dict = 0; + self->weakreflist = 0; + self->d->referredObjects = 0; + return reinterpret_cast(self); +} + + } //extern "C" namespace Shiboken @@ -381,25 +401,6 @@ void walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visi } } -PyObject* SbkBaseWrapper_TpNew(PyTypeObject* subtype, PyObject*, PyObject*) -{ - SbkObject* self = reinterpret_cast(subtype->tp_alloc(subtype, 0)); - self->d = new SbkBaseWrapperPrivate; - - SbkBaseWrapperType* sbkType = reinterpret_cast(subtype); - int numBases = sbkType->is_multicpp ? getNumberOfCppBaseClasses(subtype) : 1; - self->d->cptr = new void*[numBases]; - std::memset(self->d->cptr, 0, sizeof(void*)*numBases); - self->d->hasOwnership = 1; - self->d->containsCppWrapper = 0; - self->d->validCppObject = 0; - self->d->parentInfo = 0; - self->ob_dict = 0; - self->weakreflist = 0; - self->d->referredObjects = 0; - return reinterpret_cast(self); -} - void setTypeUserData(SbkObject* wrapper, void *user_data, DeleteUserDataFunc d_func) { SbkBaseWrapperType* ob_type = reinterpret_cast(wrapper->ob_type); @@ -714,7 +715,7 @@ PyObject* newObject(SbkBaseWrapperType* instanceType, instanceType = BindingManager::instance().resolveType(cptr, instanceType); } - SbkObject* self = reinterpret_cast(SbkBaseWrapper_TpNew(reinterpret_cast(instanceType), 0, 0)); + SbkObject* self = reinterpret_cast(SbkObjectTpNew(reinterpret_cast(instanceType), 0, 0)); self->d->cptr[0] = cptr; self->d->hasOwnership = hasOwnership; self->d->validCppObject = 1; diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 9702992a..df5f8e35 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -101,6 +101,8 @@ struct LIBSHIBOKEN_API SbkBaseWrapperType DeleteUserDataFunc d_func; }; +LIBSHIBOKEN_API PyObject* SbkObjectTpNew(PyTypeObject* subtype, PyObject*, PyObject*); + } // extern "C" namespace Shiboken @@ -167,9 +169,6 @@ LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctor #define SbkBaseWrapper_Check(op) PyObject_TypeCheck(op, (PyTypeObject*)&SbkBaseWrapper_Type) #define SbkBaseWrapper_CheckExact(op) ((op)->ob_type == &SbkBaseWrapper_Type) -LIBSHIBOKEN_API PyObject* -SbkBaseWrapper_TpNew(PyTypeObject* subtype, PyObject*, PyObject*); - /** * Increments the reference count of the referred Python object. * A previous Python object in the same position identified by the 'key' parameter From 5bd16e14f8cfe735762cf7b38f7488af6e36e94d Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 10 Nov 2010 14:19:44 -0200 Subject: [PATCH 116/564] SbkBaseWrapperType renamed to SbkObjectType. --- generator/cppgenerator.cpp | 24 ++++++++++----------- generator/headergenerator.cpp | 6 +++--- libshiboken/basewrapper.cpp | 38 +++++++++++++++++----------------- libshiboken/basewrapper.h | 14 ++++++------- libshiboken/basewrapper_p.h | 18 ++++++++-------- libshiboken/bindingmanager.cpp | 22 ++++++++++---------- libshiboken/bindingmanager.h | 6 +++--- libshiboken/conversions.h | 12 +++++------ libshiboken/typeresolver.h | 2 +- 9 files changed, 71 insertions(+), 71 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 3936d03f..29435231 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -857,8 +857,8 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun s << INDENT << "SbkObject* sbkSelf = reinterpret_cast(self);" << endl; if (metaClass->isAbstract() || metaClass->baseClassNames().size() > 1) { - s << INDENT << "SbkBaseWrapperType* type = reinterpret_cast(self->ob_type);" << endl; - s << INDENT << "SbkBaseWrapperType* myType = reinterpret_cast(" << cpythonTypeNameExt(metaClass->typeEntry()) << ");" << endl; + s << INDENT << "SbkObjectType* type = reinterpret_cast(self->ob_type);" << endl; + s << INDENT << "SbkObjectType* myType = reinterpret_cast(" << cpythonTypeNameExt(metaClass->typeEntry()) << ");" << endl; } if (metaClass->isAbstract()) { @@ -2217,12 +2217,12 @@ void CppGenerator::writeMultipleInheritanceInitializerFunction(QTextStream& s, c void CppGenerator::writeSpecialCastFunction(QTextStream& s, const AbstractMetaClass* metaClass) { QString className = metaClass->qualifiedCppName(); - s << "static void* " << cpythonSpecialCastFunctionName(metaClass) << "(void* obj, SbkBaseWrapperType* desiredType)\n"; + s << "static void* " << cpythonSpecialCastFunctionName(metaClass) << "(void* obj, SbkObjectType* desiredType)\n"; s << "{\n"; s << INDENT << className << "* me = reinterpret_cast<" << className << "*>(obj);\n"; bool firstClass = true; foreach (const AbstractMetaClass* baseClass, getAllAncestors(metaClass)) { - s << INDENT << (!firstClass ? "else " : "") << "if (desiredType == reinterpret_cast(" << cpythonTypeNameExt(baseClass->typeEntry()) << "))\n"; + s << INDENT << (!firstClass ? "else " : "") << "if (desiredType == reinterpret_cast(" << cpythonTypeNameExt(baseClass->typeEntry()) << "))\n"; Indentation indent(INDENT); s << INDENT << "return static_cast<" << baseClass->qualifiedCppName() << "*>(me);\n"; firstClass = false; @@ -2274,7 +2274,7 @@ void CppGenerator::writeExtendedToCppFunction(QTextStream& s, const TypeEntry* e void CppGenerator::writeExtendedConverterInitialization(QTextStream& s, const TypeEntry* externalType, const QList& conversions) { s << INDENT << "// Extended implicit conversions for " << externalType->targetLangPackage() << '.' << externalType->name() << endl; - s << INDENT << "shiboType = reinterpret_cast("; + s << INDENT << "shiboType = reinterpret_cast("; s << cppApiVariableName(externalType->targetLangPackage()) << '['; s << getTypeIndexVariableName(externalType) << "]);" << endl; s << INDENT << "shiboType->ext_isconvertible = " << extendedIsConvertibleFunctionName(externalType) << ';' << endl; @@ -2425,7 +2425,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* s << "// Class Definition -----------------------------------------------" << endl; s << "extern \"C\" {" << endl; - s << "static SbkBaseWrapperType " << className + "_Type" << " = { { {" << endl; + s << "static SbkObjectType " << className + "_Type" << " = { { {" << endl; s << INDENT << "PyObject_HEAD_INIT(&SbkBaseWrapperType_Type)" << endl; s << INDENT << "/*ob_size*/ 0," << endl; s << INDENT << "/*tp_name*/ \"" << metaClass->fullName() << "\"," << endl; @@ -3248,7 +3248,7 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m const AbstractMetaClass* miClass = getMultipleInheritingClass(metaClass); if (miClass && miClass != metaClass) { s << INDENT << cpythonTypeName(metaClass) << ".mi_init = "; - s << "reinterpret_cast(" + cpythonTypeNameExt(miClass->typeEntry()) + ")->mi_init;" << endl << endl; + s << "reinterpret_cast(" + cpythonTypeNameExt(miClass->typeEntry()) + ")->mi_init;" << endl << endl; } // Set typediscovery struct or fill the struct of another one @@ -3258,7 +3258,7 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m s << INDENT << cpythonTypeName(metaClass) << ".type_discovery = &" << cpythonBaseName(metaClass) << "_typeDiscovery;" << endl; s << INDENT << "Shiboken::BindingManager& bm = Shiboken::BindingManager::instance();" << endl; foreach (const AbstractMetaClass* base, baseClasses) { - s << INDENT << "bm.addClassInheritance(reinterpret_cast(" << cpythonTypeNameExt(base->typeEntry()) << "), &" << cpythonTypeName(metaClass) << ");" << endl; + s << INDENT << "bm.addClassInheritance(reinterpret_cast(" << cpythonTypeNameExt(base->typeEntry()) << "), &" << cpythonTypeName(metaClass) << ");" << endl; } } s << endl; @@ -3336,7 +3336,7 @@ void CppGenerator::writeTypeDiscoveryFunction(QTextStream& s, const AbstractMeta { QString polymorphicExpr = metaClass->typeEntry()->polymorphicIdValue(); - s << "static SbkBaseWrapperType* " << cpythonBaseName(metaClass) << "_typeDiscovery(void* cptr, SbkBaseWrapperType* instanceType)\n{" << endl; + s << "static SbkObjectType* " << cpythonBaseName(metaClass) << "_typeDiscovery(void* cptr, SbkObjectType* instanceType)\n{" << endl; if (!metaClass->baseClass()) { s << INDENT << "TypeResolver* typeResolver = TypeResolver::get(typeid(*reinterpret_cast<" @@ -3344,7 +3344,7 @@ void CppGenerator::writeTypeDiscoveryFunction(QTextStream& s, const AbstractMeta s << INDENT << "if (typeResolver)" << endl; { Indentation indent(INDENT); - s << INDENT << "return reinterpret_cast(typeResolver->pythonType());" << endl; + s << INDENT << "return reinterpret_cast(typeResolver->pythonType());" << endl; } } else if (!polymorphicExpr.isEmpty()) { polymorphicExpr = polymorphicExpr.replace("%1", " reinterpret_cast<"+metaClass->qualifiedCppName()+"*>(cptr)"); @@ -3359,7 +3359,7 @@ void CppGenerator::writeTypeDiscoveryFunction(QTextStream& s, const AbstractMeta if (ancestor->baseClass()) continue; if (ancestor->isPolymorphic()) { - s << INDENT << "if (instanceType == reinterpret_cast(Shiboken::SbkType<" + s << INDENT << "if (instanceType == reinterpret_cast(Shiboken::SbkType<" << ancestor->qualifiedCppName() << " >()) && dynamic_cast<" << metaClass->qualifiedCppName() << "*>(reinterpret_cast<"<< ancestor->qualifiedCppName() << "*>(cptr)))" << endl; Indentation indent(INDENT); @@ -3680,7 +3680,7 @@ void CppGenerator::finishGeneration() if (!extendedConverters.isEmpty()) { s << INDENT << "// Initialize extended Converters" << endl; - s << INDENT << "SbkBaseWrapperType* shiboType;" << endl << endl; + s << INDENT << "SbkObjectType* shiboType;" << endl << endl; } foreach (const TypeEntry* externalType, extendedConverters.keys()) { writeExtendedConverterInitialization(s, externalType, extendedConverters[externalType]); diff --git a/generator/headergenerator.cpp b/generator/headergenerator.cpp index 5a9721c9..4afbc1d7 100644 --- a/generator/headergenerator.cpp +++ b/generator/headergenerator.cpp @@ -434,7 +434,7 @@ void HeaderGenerator::finishGeneration() s << INDENT << metaClass->qualifiedCppName() << "* value = const_cast<" << metaClass->qualifiedCppName() << "* >(cppobj);" << endl; s << INDENT << "if (!isExactType)" << endl; s << INDENT << INDENT << "typeName = typeid(*value).name();" << endl; - s << INDENT << "PyObject* pyObj = Shiboken::SbkBaseWrapper_New(reinterpret_cast(SbkType<" << metaClass->qualifiedCppName() << " >())," + s << INDENT << "PyObject* pyObj = Shiboken::Wrapper::newObject(reinterpret_cast(SbkType<" << metaClass->qualifiedCppName() << " >())," << "value, hasOwnership, isExactType, typeName);" << endl; s << INDENT << "PySide::Signal::updateSourceObject(pyObj);" << endl; s << INDENT << "return pyObj;" << endl; @@ -531,7 +531,7 @@ void HeaderGenerator::writeTypeConverterImpl(QTextStream& s, const TypeEntry* ty } - s << INDENT << "SbkBaseWrapperType* shiboType = reinterpret_cast(SbkType<"; + s << INDENT << "SbkObjectType* shiboType = reinterpret_cast(SbkType<"; s << type->name() << " >());" << endl; s << INDENT << "return "; bool isFirst = true; @@ -561,7 +561,7 @@ void HeaderGenerator::writeTypeConverterImpl(QTextStream& s, const TypeEntry* ty s << INDENT << "if (!Shiboken_TypeCheck(pyobj, " << type->name() << ")) {" << endl; { Indentation indent(INDENT); - s << INDENT << "SbkBaseWrapperType* shiboType = reinterpret_cast(SbkType<"; + s << INDENT << "SbkObjectType* shiboType = reinterpret_cast(SbkType<"; s << type->name() << " >());" << endl; } bool firstImplicitIf = true; diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 3337a4d2..26652548 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -39,8 +39,8 @@ static PyObject* SbkBaseWrapperType_TpNew(PyTypeObject* metatype, PyObject* args PyTypeObject SbkBaseWrapperType_Type = { PyObject_HEAD_INIT(0) /*ob_size*/ 0, - /*tp_name*/ "Shiboken.BaseWrapperType", - /*tp_basicsize*/ sizeof(SbkBaseWrapperType), + /*tp_name*/ "Shiboken.ObjectType", + /*tp_basicsize*/ sizeof(SbkObjectType), /*tp_itemsize*/ 0, /*tp_dealloc*/ SbkBaseWrapperType_dealloc, /*tp_print*/ 0, @@ -100,10 +100,10 @@ static PyGetSetDef SbkBaseWrapper_getsetlist[] = { {0} // Sentinel }; -SbkBaseWrapperType SbkBaseWrapper_Type = { { { +SbkObjectType SbkBaseWrapper_Type = { { { PyObject_HEAD_INIT(&SbkBaseWrapperType_Type) /*ob_size*/ 0, - /*tp_name*/ "Shiboken.BaseWrapper", + /*tp_name*/ "Shiboken.Object", /*tp_basicsize*/ sizeof(SbkObject), /*tp_itemsize*/ 0, /*tp_dealloc*/ SbkDeallocWrapperWithPrivateDtor, @@ -165,7 +165,7 @@ void SbkDeallocWrapper(PyObject* pyObj) Shiboken::BindingManager::instance().releaseWrapper(sbkObj); if (sbkObj->d->hasOwnership) { - SbkBaseWrapperType* sbkType = reinterpret_cast(pyObj->ob_type); + SbkObjectType* sbkType = reinterpret_cast(pyObj->ob_type); if (sbkType->is_multicpp) { Shiboken::DtorCallerVisitor visitor(sbkObj); Shiboken::walkThroughClassHierarchy(pyObj->ob_type, &visitor); @@ -198,7 +198,7 @@ void SbkDeallocWrapperWithPrivateDtor(PyObject* self) void SbkBaseWrapperType_dealloc(PyObject* pyObj) { - SbkBaseWrapperType *sbkType = reinterpret_cast(pyObj->ob_type); + SbkObjectType *sbkType = reinterpret_cast(pyObj->ob_type); if(sbkType->user_data && sbkType->d_func) { sbkType->d_func(sbkType->user_data); @@ -209,14 +209,14 @@ void SbkBaseWrapperType_dealloc(PyObject* pyObj) PyObject* SbkBaseWrapperType_TpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds) { // The meta type creates a new type when the Python programmer extends a wrapped C++ class. - SbkBaseWrapperType* newType = reinterpret_cast(PyType_Type.tp_new(metatype, args, kwds)); + SbkObjectType* newType = reinterpret_cast(PyType_Type.tp_new(metatype, args, kwds)); if (!newType) return 0; - std::list bases = Shiboken::getCppBaseClasses(reinterpret_cast(newType)); + std::list bases = Shiboken::getCppBaseClasses(reinterpret_cast(newType)); if (bases.size() == 1) { - SbkBaseWrapperType* parentType = bases.front(); + SbkObjectType* parentType = bases.front(); newType->mi_offsets = parentType->mi_offsets; newType->mi_init = parentType->mi_init; newType->mi_specialcast = parentType->mi_specialcast; @@ -252,7 +252,7 @@ PyObject* SbkObjectTpNew(PyTypeObject* subtype, PyObject*, PyObject*) SbkObject* self = reinterpret_cast(subtype->tp_alloc(subtype, 0)); self->d = new SbkBaseWrapperPrivate; - SbkBaseWrapperType* sbkType = reinterpret_cast(subtype); + SbkObjectType* sbkType = reinterpret_cast(subtype); int numBases = sbkType->is_multicpp ? Shiboken::getNumberOfCppBaseClasses(subtype) : 1; self->d->cptr = new void*[numBases]; std::memset(self->d->cptr, 0, sizeof(void*)*numBases); @@ -390,7 +390,7 @@ void walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visi if (type->ob_type != &SbkBaseWrapperType_Type) { continue; } else { - SbkBaseWrapperType* sbkType = reinterpret_cast(type); + SbkObjectType* sbkType = reinterpret_cast(type); if (sbkType->is_user_type) walkThroughClassHierarchy(type, visitor); else @@ -403,7 +403,7 @@ void walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visi void setTypeUserData(SbkObject* wrapper, void *user_data, DeleteUserDataFunc d_func) { - SbkBaseWrapperType* ob_type = reinterpret_cast(wrapper->ob_type); + SbkObjectType* ob_type = reinterpret_cast(wrapper->ob_type); if (ob_type->user_data) ob_type->d_func(ob_type->user_data); @@ -413,7 +413,7 @@ void setTypeUserData(SbkObject* wrapper, void *user_data, DeleteUserDataFunc d_f void* getTypeUserData(SbkObject* wrapper) { - return reinterpret_cast(wrapper->ob_type)->user_data; + return reinterpret_cast(wrapper->ob_type)->user_data; } void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append) @@ -474,7 +474,7 @@ bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr) // Wrapper metatype and base type ---------------------------------------------------------- -void DtorCallerVisitor::visit(SbkBaseWrapperType* node) +void DtorCallerVisitor::visit(SbkObjectType* node) { node->cpp_dtor(m_pyObj->d->cptr[m_count]); m_count++; @@ -548,7 +548,7 @@ class FindBaseTypeVisitor : public HierarchyVisitor { public: FindBaseTypeVisitor(PyTypeObject* typeToFind) : m_found(false), m_typeToFind(typeToFind) {} - virtual void visit(SbkBaseWrapperType* node) + virtual void visit(SbkObjectType* node) { if (reinterpret_cast(node) == m_typeToFind) { m_found = true; @@ -666,7 +666,7 @@ void* cppPointer(PyObject* pyObj, PyTypeObject* desiredType) assert(isShibokenType(pyObj)); PyTypeObject* type = pyObj->ob_type; int idx = 0; - if (reinterpret_cast(type)->is_multicpp) + if (reinterpret_cast(type)->is_multicpp) idx = getTypeIndexOnHierarchy(type, desiredType); return reinterpret_cast(pyObj)->d->cptr[idx]; } @@ -674,7 +674,7 @@ void* cppPointer(PyObject* pyObj, PyTypeObject* desiredType) bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr) { int idx = 0; - if (reinterpret_cast(sbkObj->ob_type)->is_multicpp) + if (reinterpret_cast(sbkObj->ob_type)->is_multicpp) idx = getTypeIndexOnHierarchy(sbkObj->ob_type, desiredType); bool alreadyInitialized = sbkObj->d->cptr[idx]; @@ -697,7 +697,7 @@ bool isValid(PyObject* pyObj) return false; } -PyObject* newObject(SbkBaseWrapperType* instanceType, +PyObject* newObject(SbkObjectType* instanceType, void* cptr, bool hasOwnership, bool isExactType, @@ -709,7 +709,7 @@ PyObject* newObject(SbkBaseWrapperType* instanceType, if (typeName) { tr = TypeResolver::get(typeName); if (tr) - instanceType = reinterpret_cast(tr->pythonType()); + instanceType = reinterpret_cast(tr->pythonType()); } if (!tr) instanceType = BindingManager::instance().resolveType(cptr, instanceType); diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index df5f8e35..fbb558f7 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -51,7 +51,7 @@ struct LIBSHIBOKEN_API SbkObject LIBSHIBOKEN_API void SbkDeallocWrapper(PyObject* pyObj); LIBSHIBOKEN_API void SbkDeallocWrapperWithPrivateDtor(PyObject* self); -struct SbkBaseWrapperType; +struct SbkObjectType; /// Function signature for the multiple inheritance information initializers that should be provided by classes with multiple inheritance. typedef int* (*MultipleInheritanceInitFunction)(const void*); @@ -61,9 +61,9 @@ typedef int* (*MultipleInheritanceInitFunction)(const void*); * part of a multiple inheritance hierarchy. * The implementation of this function is auto generated by the generator and you don't need to care about it. */ -typedef void* (*SpecialCastFunction)(void*, SbkBaseWrapperType*); +typedef void* (*SpecialCastFunction)(void*, SbkObjectType*); typedef void* (*ObjectCopierFunction)(const void*); -typedef SbkBaseWrapperType* (*TypeDiscoveryFunc)(void*, SbkBaseWrapperType*); +typedef SbkObjectType* (*TypeDiscoveryFunc)(void*, SbkObjectType*); typedef void* (*ExtendedToCppFunc)(PyObject*); typedef bool (*ExtendedIsConvertibleFunc)(PyObject*); @@ -72,10 +72,10 @@ typedef bool (*ExtendedIsConvertibleFunc)(PyObject*); typedef void (*DeleteUserDataFunc)(void*); extern LIBSHIBOKEN_API PyTypeObject SbkBaseWrapperType_Type; -extern LIBSHIBOKEN_API SbkBaseWrapperType SbkBaseWrapper_Type; +extern LIBSHIBOKEN_API SbkObjectType SbkBaseWrapper_Type; /// PyTypeObject extended with C++ multiple inheritance information. -struct LIBSHIBOKEN_API SbkBaseWrapperType +struct LIBSHIBOKEN_API SbkObjectType { PyHeapTypeObject super; int* mi_offsets; @@ -146,7 +146,7 @@ inline bool isShibokenType(PyObject*& pyObj) */ inline bool isUserType(PyObject*& pyObj) { - return isShibokenType(pyObj) && reinterpret_cast(pyObj->ob_type)->is_user_type; + return isShibokenType(pyObj) && reinterpret_cast(pyObj->ob_type)->is_user_type; } /** @@ -195,7 +195,7 @@ LIBSHIBOKEN_API void setErrorAboutWrongArguments(PyObject* args, const char* fun namespace Wrapper { -LIBSHIBOKEN_API PyObject* newObject(SbkBaseWrapperType* instanceType, +LIBSHIBOKEN_API PyObject* newObject(SbkObjectType* instanceType, void* cptr, bool hasOwnership = true, bool isExactType = false, diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h index 6b8b9ab3..3e0757f2 100644 --- a/libshiboken/basewrapper_p.h +++ b/libshiboken/basewrapper_p.h @@ -28,7 +28,7 @@ #include struct SbkObject; -struct SbkBaseWrapperType; +struct SbkObjectType; namespace Shiboken { @@ -97,7 +97,7 @@ class HierarchyVisitor public: HierarchyVisitor() : m_wasFinished(false) {} virtual ~HierarchyVisitor() {} - virtual void visit(SbkBaseWrapperType* node) = 0; + virtual void visit(SbkObjectType* node) = 0; void finish() { m_wasFinished = true; }; bool wasFinished() const { return m_wasFinished; } private: @@ -109,7 +109,7 @@ class BaseCountVisitor : public HierarchyVisitor public: BaseCountVisitor() : m_count(0) {} - void visit(SbkBaseWrapperType*) + void visit(SbkObjectType*) { m_count++; } @@ -124,21 +124,21 @@ class BaseAccumulatorVisitor : public HierarchyVisitor public: BaseAccumulatorVisitor() {} - void visit(SbkBaseWrapperType* node) + void visit(SbkObjectType* node) { m_bases.push_back(node); } - std::list bases() const { return m_bases; } + std::list bases() const { return m_bases; } private: - std::list m_bases; + std::list m_bases; }; class GetIndexVisitor : public HierarchyVisitor { public: GetIndexVisitor(PyTypeObject* desiredType) : m_index(-1), m_desiredType(desiredType) {} - virtual void visit(SbkBaseWrapperType* node) + virtual void visit(SbkObjectType* node) { m_index++; if (PyType_IsSubtype(reinterpret_cast(node), m_desiredType)) @@ -155,7 +155,7 @@ class DtorCallerVisitor : public HierarchyVisitor { public: DtorCallerVisitor(SbkObject* pyObj) : m_count(0), m_pyObj(pyObj) {} - void visit(SbkBaseWrapperType* node); + void visit(SbkObjectType* node); private: int m_count; SbkObject* m_pyObj; @@ -183,7 +183,7 @@ inline int getNumberOfCppBaseClasses(PyTypeObject* baseType) return visitor.count(); } -inline std::list getCppBaseClasses(PyTypeObject* baseType) +inline std::list getCppBaseClasses(PyTypeObject* baseType) { BaseAccumulatorVisitor visitor; walkThroughClassHierarchy(baseType, &visitor); diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index 5e0cbf3d..183c0c05 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -37,8 +37,8 @@ typedef google::dense_hash_map WrapperMap; class Graph { public: - typedef std::list NodeList; - typedef google::dense_hash_map Edges; + typedef std::list NodeList; + typedef google::dense_hash_map Edges; Edges m_edges; @@ -47,7 +47,7 @@ class Graph m_edges.set_empty_key(0); } - void addEdge(SbkBaseWrapperType* from, SbkBaseWrapperType* to) + void addEdge(SbkObjectType* from, SbkObjectType* to) { m_edges[from].push_back(to); } @@ -61,7 +61,7 @@ class Graph Edges::const_iterator i = m_edges.begin(); for (; i != m_edges.end(); ++i) { - SbkBaseWrapperType* node1 = i->first; + SbkObjectType* node1 = i->first; const NodeList& nodeList = i->second; NodeList::const_iterator j = nodeList.begin(); for (; j != nodeList.end(); ++j) @@ -71,14 +71,14 @@ class Graph } #endif - SbkBaseWrapperType* identifyType(void* cptr, SbkBaseWrapperType* type, SbkBaseWrapperType* baseType) const + SbkObjectType* identifyType(void* cptr, SbkObjectType* type, SbkObjectType* baseType) const { Edges::const_iterator edgesIt = m_edges.find(type); if (edgesIt != m_edges.end()) { const NodeList& adjNodes = m_edges.find(type)->second; NodeList::const_iterator i = adjNodes.begin(); for (; i != adjNodes.end(); ++i) { - SbkBaseWrapperType* newType = identifyType(cptr, *i, baseType); + SbkObjectType* newType = identifyType(cptr, *i, baseType); if (newType) return newType; } @@ -164,7 +164,7 @@ bool BindingManager::hasWrapper(const void* cptr) } void BindingManager::registerWrapper(SbkObject* pyObj, void* cptr) { - SbkBaseWrapperType* instanceType = reinterpret_cast(pyObj->ob_type); + SbkObjectType* instanceType = reinterpret_cast(pyObj->ob_type); if (instanceType->mi_init && !instanceType->mi_offsets) instanceType->mi_offsets = instanceType->mi_init(cptr); @@ -181,7 +181,7 @@ void BindingManager::registerWrapper(SbkObject* pyObj, void* cptr) void BindingManager::releaseWrapper(SbkObject* sbkObj) { - SbkBaseWrapperType* sbkType = reinterpret_cast(sbkObj->ob_type); + SbkObjectType* sbkType = reinterpret_cast(sbkObj->ob_type); int numBases = sbkType->is_multicpp ? getNumberOfCppBaseClasses(sbkObj->ob_type) : 1; void** cptrs = reinterpret_cast(sbkObj)->d->cptr; @@ -333,14 +333,14 @@ void BindingManager::transferOwnershipToCpp(SbkObject* wrapper) invalidateWrapper(wrapper); } -void BindingManager::addClassInheritance(SbkBaseWrapperType* parent, SbkBaseWrapperType* child) +void BindingManager::addClassInheritance(SbkObjectType* parent, SbkObjectType* child) { m_d->classHierarchy.addEdge(parent, child); } -SbkBaseWrapperType* BindingManager::resolveType(void* cptr, SbkBaseWrapperType* type) +SbkObjectType* BindingManager::resolveType(void* cptr, SbkObjectType* type) { - SbkBaseWrapperType* identifiedType = m_d->classHierarchy.identifyType(cptr, type, type); + SbkObjectType* identifiedType = m_d->classHierarchy.identifyType(cptr, type, type); return identifiedType ? identifiedType : type; } diff --git a/libshiboken/bindingmanager.h b/libshiboken/bindingmanager.h index 8a6607fd..c1926e5e 100644 --- a/libshiboken/bindingmanager.h +++ b/libshiboken/bindingmanager.h @@ -28,7 +28,7 @@ #include "shibokenmacros.h" struct SbkObject; -struct SbkBaseWrapperType; +struct SbkObjectType; namespace Shiboken { @@ -56,8 +56,8 @@ class LIBSHIBOKEN_API BindingManager void transferOwnershipToCpp(SbkObject* wrapper); /// Convenience method to call transferOwnershipToCpp with a properly cast SbkBaseWrapper. void transferOwnershipToCpp(PyObject* wrapper); - void addClassInheritance(SbkBaseWrapperType* parent, SbkBaseWrapperType* child); - SbkBaseWrapperType* resolveType(void* cptr, SbkBaseWrapperType* type); + void addClassInheritance(SbkObjectType* parent, SbkObjectType* child); + SbkObjectType* resolveType(void* cptr, SbkObjectType* type); /// Called by wrapper destructor void destroyWrapper(const void* cptr); diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index a590ea19..dff14478 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -99,7 +99,7 @@ struct CppObjectCopier { static inline T* copy(const T& obj) { - return reinterpret_cast(reinterpret_cast(SbkType())->obj_copier(&obj)); + return reinterpret_cast(reinterpret_cast(SbkType())->obj_copier(&obj)); } }; @@ -113,7 +113,7 @@ inline PyObject* createWrapper(const T* cppobj, bool hasOwnership = false, bool const char* typeName = 0; if (!isExactType) typeName = typeid(*const_cast(cppobj)).name(); - return Wrapper::newObject(reinterpret_cast(SbkType()), + return Wrapper::newObject(reinterpret_cast(SbkType()), const_cast(cppobj), hasOwnership, isExactType, typeName); } @@ -215,7 +215,7 @@ struct ValueTypeConverter { if (PyObject_TypeCheck(pyobj, SbkType())) return true; - SbkBaseWrapperType* shiboType = reinterpret_cast(SbkType()); + SbkObjectType* shiboType = reinterpret_cast(SbkType()); if (shiboType->ext_isconvertible) return shiboType->ext_isconvertible(pyobj); return false; @@ -235,7 +235,7 @@ struct ValueTypeConverter static inline T toCpp(PyObject* pyobj) { if (!PyObject_TypeCheck(pyobj, SbkType())) { - SbkBaseWrapperType* shiboType = reinterpret_cast(SbkType()); + SbkObjectType* shiboType = reinterpret_cast(SbkType()); if (shiboType->ext_tocpp && isConvertible(pyobj)) { T* cptr = reinterpret_cast(shiboType->ext_tocpp(pyobj)); std::auto_ptr cptr_auto_ptr(cptr); @@ -275,9 +275,9 @@ struct ObjectTypeConverter { if (pyobj == Py_None) return 0; - SbkBaseWrapperType* shiboType = reinterpret_cast(pyobj->ob_type); + SbkObjectType* shiboType = reinterpret_cast(pyobj->ob_type); if (shiboType->mi_specialcast) - return (T*) shiboType->mi_specialcast(Wrapper::cppPointer(pyobj, SbkType()), reinterpret_cast(SbkType())); + return (T*) shiboType->mi_specialcast(Wrapper::cppPointer(pyobj, SbkType()), reinterpret_cast(SbkType())); return (T*) Wrapper::cppPointer(pyobj, SbkType()); } }; diff --git a/libshiboken/typeresolver.h b/libshiboken/typeresolver.h index 4e23b970..bec99090 100644 --- a/libshiboken/typeresolver.h +++ b/libshiboken/typeresolver.h @@ -26,7 +26,7 @@ #include "shibokenmacros.h" #include "conversions.h" -class SbkBaseWrapperType; +class SbkObjectType; namespace Shiboken { From f7ec12bd0547fafd94d114bb78c9ee0e48686043 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 10 Nov 2010 14:24:49 -0200 Subject: [PATCH 117/564] Rename some internal functions and structs. --- libshiboken/basewrapper.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 26652548..f7ff1dc5 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -33,8 +33,8 @@ extern "C" { -static void SbkBaseWrapperType_dealloc(PyObject* pyObj); -static PyObject* SbkBaseWrapperType_TpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds); +static void SbkObjectTypeDealloc(PyObject* pyObj); +static PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds); PyTypeObject SbkBaseWrapperType_Type = { PyObject_HEAD_INIT(0) @@ -42,7 +42,7 @@ PyTypeObject SbkBaseWrapperType_Type = { /*tp_name*/ "Shiboken.ObjectType", /*tp_basicsize*/ sizeof(SbkObjectType), /*tp_itemsize*/ 0, - /*tp_dealloc*/ SbkBaseWrapperType_dealloc, + /*tp_dealloc*/ SbkObjectTypeDealloc, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, @@ -75,7 +75,7 @@ PyTypeObject SbkBaseWrapperType_Type = { /*tp_dictoffset*/ 0, /*tp_init*/ 0, /*tp_alloc*/ 0, - /*tp_new*/ SbkBaseWrapperType_TpNew, + /*tp_new*/ SbkObjectTypeTpNew, /*tp_free*/ 0, /*tp_is_gc*/ 0, /*tp_bases*/ 0, @@ -85,7 +85,7 @@ PyTypeObject SbkBaseWrapperType_Type = { /*tp_weaklist*/ 0 }; -static PyObject* SbkBaseWrapper_get_dict(SbkObject* obj) +static PyObject* SbkObjectGetDict(SbkObject* obj) { if (!obj->ob_dict) obj->ob_dict = PyDict_New(); @@ -95,8 +95,8 @@ static PyObject* SbkBaseWrapper_get_dict(SbkObject* obj) return obj->ob_dict; } -static PyGetSetDef SbkBaseWrapper_getsetlist[] = { - {const_cast("__dict__"), (getter)SbkBaseWrapper_get_dict, 0}, +static PyGetSetDef SbkObjectGetSetList[] = { + {const_cast("__dict__"), (getter)SbkObjectGetDict, 0}, {0} // Sentinel }; @@ -131,7 +131,7 @@ SbkObjectType SbkBaseWrapper_Type = { { { /*tp_iternext*/ 0, /*tp_methods*/ 0, /*tp_members*/ 0, - /*tp_getset*/ SbkBaseWrapper_getsetlist, + /*tp_getset*/ SbkObjectGetSetList, /*tp_base*/ 0, /*tp_dict*/ 0, /*tp_descr_get*/ 0, @@ -196,7 +196,7 @@ void SbkDeallocWrapperWithPrivateDtor(PyObject* self) self->ob_type->tp_free(self); } -void SbkBaseWrapperType_dealloc(PyObject* pyObj) +void SbkObjectTypeDealloc(PyObject* pyObj) { SbkObjectType *sbkType = reinterpret_cast(pyObj->ob_type); @@ -206,7 +206,7 @@ void SbkBaseWrapperType_dealloc(PyObject* pyObj) } } -PyObject* SbkBaseWrapperType_TpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds) +PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds) { // The meta type creates a new type when the Python programmer extends a wrapped C++ class. SbkObjectType* newType = reinterpret_cast(PyType_Type.tp_new(metatype, args, kwds)); From 7090a14a3412af1d857d3a995dfdb7e575ebf22a Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 10 Nov 2010 14:30:42 -0200 Subject: [PATCH 118/564] SbkBaseWrapper_Type variable renamed to SbkObject_Type --- generator/cppgenerator.cpp | 2 +- libshiboken/basewrapper.cpp | 4 ++-- libshiboken/basewrapper.h | 6 +++--- tests/samplebinding/typesystem_sample.xml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 29435231..8e0706bf 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2341,7 +2341,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* tp_as_sequence = QString("&Py%1_as_sequence").arg(cppClassName); if (!metaClass->baseClass()) - baseClassName = "reinterpret_cast(&SbkBaseWrapper_Type)"; + baseClassName = "reinterpret_cast(&SbkObject_Type)"; if (metaClass->isNamespace() || metaClass->hasPrivateDestructor()) { tp_flags = "Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES"; diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index f7ff1dc5..9fdcc456 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -100,7 +100,7 @@ static PyGetSetDef SbkObjectGetSetList[] = { {0} // Sentinel }; -SbkObjectType SbkBaseWrapper_Type = { { { +SbkObjectType SbkObject_Type = { { { PyObject_HEAD_INIT(&SbkBaseWrapperType_Type) /*ob_size*/ 0, /*tp_name*/ "Shiboken.Object", @@ -497,7 +497,7 @@ void initShiboken() if (PyType_Ready(&SbkBaseWrapperType_Type) < 0) Py_FatalError("[libshiboken] Failed to initialise Shiboken.BaseWrapperType metatype."); - if (PyType_Ready((PyTypeObject *)&SbkBaseWrapper_Type) < 0) + if (PyType_Ready((PyTypeObject *)&SbkObject_Type) < 0) Py_FatalError("[libshiboken] Failed to initialise Shiboken.BaseWrapper type."); shibokenAlreadInitialised = true; diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index fbb558f7..3e42ee86 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -72,7 +72,7 @@ typedef bool (*ExtendedIsConvertibleFunc)(PyObject*); typedef void (*DeleteUserDataFunc)(void*); extern LIBSHIBOKEN_API PyTypeObject SbkBaseWrapperType_Type; -extern LIBSHIBOKEN_API SbkObjectType SbkBaseWrapper_Type; +extern LIBSHIBOKEN_API SbkObjectType SbkObject_Type; /// PyTypeObject extended with C++ multiple inheritance information. struct LIBSHIBOKEN_API SbkObjectType @@ -166,8 +166,8 @@ LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctor */ #define Shiboken_TypeCheck(pyobj, type) (PyObject_TypeCheck(pyobj, SbkType())) -#define SbkBaseWrapper_Check(op) PyObject_TypeCheck(op, (PyTypeObject*)&SbkBaseWrapper_Type) -#define SbkBaseWrapper_CheckExact(op) ((op)->ob_type == &SbkBaseWrapper_Type) +#define SbkBaseWrapper_Check(op) PyObject_TypeCheck(op, (PyTypeObject*)&SbkObject_Type) +#define SbkBaseWrapper_CheckExact(op) ((op)->ob_type == &SbkObject_Type) /** * Increments the reference count of the referred Python object. diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 3285da13..d2d1266c 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -1176,7 +1176,7 @@ %RETURN_TYPE %0 = %TYPE::%FUNCTION_NAME(); - %PYARG_0 = Shiboken::Wrapper::newObject(&SbkBaseWrapper_Type, %0, false, false); + %PYARG_0 = Shiboken::Wrapper::newObject(&SbkObject_Type, %0, false, false); From 50fae8be6d673c56a10cd414e9f7da1a5151b062 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 10 Nov 2010 14:36:07 -0200 Subject: [PATCH 119/564] Variable SbkBaseWrapperType_Type renamed to SbkObjectType_Type --- generator/cppgenerator.cpp | 2 +- generator/shibokengenerator.cpp | 2 +- libshiboken/basewrapper.cpp | 10 +++++----- libshiboken/basewrapper.h | 4 ++-- tests/samplebinding/typesystem_sample.xml | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 8e0706bf..a5446037 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2426,7 +2426,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* s << "// Class Definition -----------------------------------------------" << endl; s << "extern \"C\" {" << endl; s << "static SbkObjectType " << className + "_Type" << " = { { {" << endl; - s << INDENT << "PyObject_HEAD_INIT(&SbkBaseWrapperType_Type)" << endl; + s << INDENT << "PyObject_HEAD_INIT(&SbkObjectType_Type)" << endl; s << INDENT << "/*ob_size*/ 0," << endl; s << INDENT << "/*tp_name*/ \"" << metaClass->fullName() << "\"," << endl; s << INDENT << "/*tp_basicsize*/ sizeof(SbkObject)," << endl; diff --git a/generator/shibokengenerator.cpp b/generator/shibokengenerator.cpp index 67f5fca8..4990eb19 100644 --- a/generator/shibokengenerator.cpp +++ b/generator/shibokengenerator.cpp @@ -598,7 +598,7 @@ QString ShibokenGenerator::cpythonBaseName(const TypeEntry* type) { QString baseName; if ((type->isObject() || type->isValue() || type->isNamespace())) { // && !type->isReference()) { - baseName = QString("Sbk") + type->name(); + baseName = "Sbk_" + type->name(); } else if (type->isPrimitive()) { const PrimitiveTypeEntry* ptype = (const PrimitiveTypeEntry*) type; while (ptype->basicAliasedTypeEntry()) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 9fdcc456..0e375cfc 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -36,7 +36,7 @@ extern "C" static void SbkObjectTypeDealloc(PyObject* pyObj); static PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds); -PyTypeObject SbkBaseWrapperType_Type = { +PyTypeObject SbkObjectType_Type = { PyObject_HEAD_INIT(0) /*ob_size*/ 0, /*tp_name*/ "Shiboken.ObjectType", @@ -101,7 +101,7 @@ static PyGetSetDef SbkObjectGetSetList[] = { }; SbkObjectType SbkObject_Type = { { { - PyObject_HEAD_INIT(&SbkBaseWrapperType_Type) + PyObject_HEAD_INIT(&SbkObjectType_Type) /*ob_size*/ 0, /*tp_name*/ "Shiboken.Object", /*tp_basicsize*/ sizeof(SbkObject), @@ -387,7 +387,7 @@ void walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visi for (int i = 0; i < numBases; ++i) { PyTypeObject* type = reinterpret_cast(PyTuple_GET_ITEM(bases, i)); - if (type->ob_type != &SbkBaseWrapperType_Type) { + if (type->ob_type != &SbkObjectType_Type) { continue; } else { SbkObjectType* sbkType = reinterpret_cast(type); @@ -494,7 +494,7 @@ void initShiboken() if (PyType_Ready(&SbkEnumType_Type) < 0) Py_FatalError("[libshiboken] Failed to initialise Shiboken.SbkEnumType metatype."); - if (PyType_Ready(&SbkBaseWrapperType_Type) < 0) + if (PyType_Ready(&SbkObjectType_Type) < 0) Py_FatalError("[libshiboken] Failed to initialise Shiboken.BaseWrapperType metatype."); if (PyType_Ready((PyTypeObject *)&SbkObject_Type) < 0) @@ -689,7 +689,7 @@ bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr) bool isValid(PyObject* pyObj) { if (!pyObj || pyObj == Py_None - || pyObj->ob_type->ob_type != &SbkBaseWrapperType_Type + || pyObj->ob_type->ob_type != &SbkObjectType_Type || ((SbkObject*)pyObj)->d->validCppObject) { return true; } diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 3e42ee86..c6b936b7 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -71,7 +71,7 @@ typedef bool (*ExtendedIsConvertibleFunc)(PyObject*); // Used in userdata dealloc function typedef void (*DeleteUserDataFunc)(void*); -extern LIBSHIBOKEN_API PyTypeObject SbkBaseWrapperType_Type; +extern LIBSHIBOKEN_API PyTypeObject SbkObjectType_Type; extern LIBSHIBOKEN_API SbkObjectType SbkObject_Type; /// PyTypeObject extended with C++ multiple inheritance information. @@ -138,7 +138,7 @@ LIBSHIBOKEN_API void destroyParentInfo(SbkObject* obj, bool removeFromParent = t */ inline bool isShibokenType(PyObject*& pyObj) { - return pyObj->ob_type->ob_type == &SbkBaseWrapperType_Type; + return pyObj->ob_type->ob_type == &SbkObjectType_Type; } /** diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index d2d1266c..f6c049b8 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -1114,7 +1114,7 @@ PyObject* args = Py_BuildValue("(iO)", _i, _value); - PyObject* result = SbkStrFunc_set_char(self, args); + PyObject* result = Sbk_StrFunc_set_char(self, args); Py_DECREF(args); int ok = result == Py_True; if (result) { From f2a10c2257e40a7f24c457ad45d875f997a2cc5a Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 10 Nov 2010 14:45:28 -0200 Subject: [PATCH 120/564] Removed macros SbkBaseWrapper_Check and SbkBaseWrapper_CheckExact. --- generator/cppgenerator.cpp | 2 +- libshiboken/basewrapper.h | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index a5446037..e69ff3c7 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -1166,7 +1166,7 @@ void CppGenerator::writeMethodWrapper(QTextStream& s, const AbstractMetaFunction s << INDENT << "if (!isReverse" << endl; { Indentation indent(INDENT); - s << INDENT << "&& SbkBaseWrapper_Check(arg)" << endl; + s << INDENT << "&& Shiboken::isShibokenType(arg)" << endl; s << INDENT << "&& !PyObject_TypeCheck(arg, self->ob_type)" << endl; s << INDENT << "&& PyObject_HasAttrString(arg, const_cast(\"" << revOpName << "\"))) {" << endl; // This PyObject_CallMethod call will emit lots of warnings like diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index c6b936b7..40d7b22e 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -166,9 +166,6 @@ LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctor */ #define Shiboken_TypeCheck(pyobj, type) (PyObject_TypeCheck(pyobj, SbkType())) -#define SbkBaseWrapper_Check(op) PyObject_TypeCheck(op, (PyTypeObject*)&SbkObject_Type) -#define SbkBaseWrapper_CheckExact(op) ((op)->ob_type == &SbkObject_Type) - /** * Increments the reference count of the referred Python object. * A previous Python object in the same position identified by the 'key' parameter From 5c813360b2f647753bfbacaf705504b7710d613c Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 10 Nov 2010 15:30:08 -0200 Subject: [PATCH 121/564] Remove macro Shiboken_TypeCheck --- generator/headergenerator.cpp | 26 ++++++-------------------- libshiboken/basewrapper.h | 5 ----- libshiboken/conversions.h | 4 +--- 3 files changed, 7 insertions(+), 28 deletions(-) diff --git a/generator/headergenerator.cpp b/generator/headergenerator.cpp index 4afbc1d7..d9560d2a 100644 --- a/generator/headergenerator.cpp +++ b/generator/headergenerator.cpp @@ -558,23 +558,17 @@ void HeaderGenerator::writeTypeConverterImpl(QTextStream& s, const TypeEntry* ty s << "inline " << type->name() << " Shiboken::Converter<" << type->name() << " >::toCpp(PyObject* pyobj)" << endl; s << '{' << endl; - s << INDENT << "if (!Shiboken_TypeCheck(pyobj, " << type->name() << ")) {" << endl; + s << INDENT << "if (PyObject_TypeCheck(pyobj, SbkType<" << type->qualifiedCppName() << ">()))" << endl; { Indentation indent(INDENT); - s << INDENT << "SbkObjectType* shiboType = reinterpret_cast(SbkType<"; - s << type->name() << " >());" << endl; + s << INDENT << "return *" << cpythonWrapperCPtr(type, "pyobj") << ';' << endl; } - bool firstImplicitIf = true; + foreach (const AbstractMetaFunction* ctor, implicitConvs) { if (ctor->isModifiedRemoved()) continue; - Indentation indent(INDENT); - s << INDENT; - if (firstImplicitIf) - firstImplicitIf = false; - else - s << "else "; + s << INDENT << "else "; QString typeCheck; QString toCppConv; @@ -597,20 +591,12 @@ void HeaderGenerator::writeTypeConverterImpl(QTextStream& s, const TypeEntry* ty } { - Indentation indent(INDENT); - s << INDENT << "else if (shiboType->ext_isconvertible && shiboType->ext_tocpp && shiboType->ext_isconvertible(pyobj)) {" << endl; + s << INDENT << "else" << endl; { Indentation indent(INDENT); - s << INDENT << type->name() << "* cptr = reinterpret_cast<" << type->name() << "*>(shiboType->ext_tocpp(pyobj));" << endl; - s << INDENT << "std::auto_ptr<" << type->name() << " > cptr_auto_ptr(cptr);" << endl; - s << INDENT << "return *cptr;" << endl; + s << INDENT << "return Shiboken::ValueTypeConverter<" << type->qualifiedCppName() << " >::toCpp(pyobj);" << endl; } - s << INDENT << '}' << endl; } - - s << INDENT << '}' << endl; - - s << INDENT << "return *" << cpythonWrapperCPtr(type, "pyobj") << ';' << endl; s << '}' << endl << endl; } diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 40d7b22e..aeed8917 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -161,11 +161,6 @@ LIBSHIBOKEN_API void* getTypeUserData(SbkObject* wrapper); */ LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType); -/** - * Shiboken_TypeCheck macro performs a type check using the values registered with SbkType<>() template. - */ -#define Shiboken_TypeCheck(pyobj, type) (PyObject_TypeCheck(pyobj, SbkType())) - /** * Increments the reference count of the referred Python object. * A previous Python object in the same position identified by the 'key' parameter diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index dff14478..c52e1e4a 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -149,12 +149,10 @@ struct Converter static T* toCpp(PyObject* pyobj) { - if (Shiboken_TypeCheck(pyobj, T)) + if (PyObject_TypeCheck(pyobj, SbkType())) return (T*) Wrapper::cppPointer(pyobj, SbkType()); - else if (Converter::isConvertible(pyobj)) return CppObjectCopier::copy(Converter::toCpp(pyobj)); - else if (pyobj == Py_None) return 0; From c984b7ee0adf8aebbb45f826dd18a6be8d36d5ec Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 10 Nov 2010 15:32:48 -0200 Subject: [PATCH 122/564] SbkBaseWrapperPrivate renamed to SbkObjectPrivate Reviewer: Luciano Wolf Marcelo Lira --- libshiboken/basewrapper.cpp | 2 +- libshiboken/basewrapper.h | 4 ++-- libshiboken/basewrapper_p.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 0e375cfc..fd9d8dec 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -250,7 +250,7 @@ PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* k PyObject* SbkObjectTpNew(PyTypeObject* subtype, PyObject*, PyObject*) { SbkObject* self = reinterpret_cast(subtype->tp_alloc(subtype, 0)); - self->d = new SbkBaseWrapperPrivate; + self->d = new SbkObjectPrivate; SbkObjectType* sbkType = reinterpret_cast(subtype); int numBases = sbkType->is_multicpp ? Shiboken::getNumberOfCppBaseClasses(subtype) : 1; diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index aeed8917..2c6c9c96 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -33,7 +33,7 @@ extern "C" { -struct SbkBaseWrapperPrivate; +struct SbkObjectPrivate; /// Base Python object for all the wrapped C++ classes. struct LIBSHIBOKEN_API SbkObject @@ -43,7 +43,7 @@ struct LIBSHIBOKEN_API SbkObject PyObject* ob_dict; /// List of weak references PyObject* weakreflist; - SbkBaseWrapperPrivate* d; + SbkObjectPrivate* d; }; diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h index 3e0757f2..6cd4b31f 100644 --- a/libshiboken/basewrapper_p.h +++ b/libshiboken/basewrapper_p.h @@ -64,7 +64,7 @@ extern "C" * \internal * Private data for SbkBaseWrapper */ -struct SbkBaseWrapperPrivate +struct SbkObjectPrivate { /// Pointer to the C++ class. void** cptr; From 9b0ebbdba7a3d94611875b368ef1d9abb0d038c5 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 10 Nov 2010 16:35:00 -0200 Subject: [PATCH 123/564] Added Shiboken::Wrapper::hasOwnership function. --- libshiboken/basewrapper.cpp | 5 +++++ libshiboken/basewrapper.h | 1 + 2 files changed, 6 insertions(+) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index fd9d8dec..0214998a 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -641,6 +641,11 @@ bool hasCppWrapper(SbkObject* pyObj) return pyObj->d->containsCppWrapper; } +bool hasOwnership(SbkObject* pyObj) +{ + return pyObj->d->hasOwnership; +} + void getOwnership(SbkObject* pyObj) { pyObj->d->hasOwnership = true; diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 2c6c9c96..bc3ecf53 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -197,6 +197,7 @@ LIBSHIBOKEN_API void setValidCpp(SbkObject* pyObj, bool value); LIBSHIBOKEN_API void setHasCppWrapper(SbkObject* pyObj, bool value); LIBSHIBOKEN_API bool hasCppWrapper(SbkObject* pyObj); +LIBSHIBOKEN_API bool hasOwnership(SbkObject* pyObj); LIBSHIBOKEN_API void getOwnership(PyObject* pyObj); LIBSHIBOKEN_API void getOwnership(SbkObject* pyObj); LIBSHIBOKEN_API void releaseOwnership(PyObject* pyObj); From 25b7f82404ea78fe3053cebad52a3404e82bf71d Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 10 Nov 2010 16:35:23 -0200 Subject: [PATCH 124/564] Changed signature of cppPointer to receive SbkObject* instead of PyObject*. --- libshiboken/basewrapper.cpp | 5 ++--- libshiboken/basewrapper.h | 2 +- libshiboken/conversions.h | 10 +++++----- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 0214998a..af61aa00 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -666,14 +666,13 @@ void releaseOwnership(PyObject* pyObj) setSequenceOwnership(pyObj, false); } -void* cppPointer(PyObject* pyObj, PyTypeObject* desiredType) +void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType) { - assert(isShibokenType(pyObj)); PyTypeObject* type = pyObj->ob_type; int idx = 0; if (reinterpret_cast(type)->is_multicpp) idx = getTypeIndexOnHierarchy(type, desiredType); - return reinterpret_cast(pyObj)->d->cptr[idx]; + return pyObj->d->cptr[idx]; } bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr) diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index bc3ecf53..0c85e907 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -206,7 +206,7 @@ LIBSHIBOKEN_API void releaseOwnership(SbkObject* pyObj); /** * Get the C++ pointer of type \p desiredType from a Python object. */ -LIBSHIBOKEN_API void* cppPointer(PyObject* pyObj, PyTypeObject* desiredType); +LIBSHIBOKEN_API void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType); /** * Set the C++ pointer of type \p desiredType of a Python object. diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index c52e1e4a..d8e28371 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -150,7 +150,7 @@ struct Converter static T* toCpp(PyObject* pyobj) { if (PyObject_TypeCheck(pyobj, SbkType())) - return (T*) Wrapper::cppPointer(pyobj, SbkType()); + return (T*) Wrapper::cppPointer(reinterpret_cast(pyobj), SbkType()); else if (Converter::isConvertible(pyobj)) return CppObjectCopier::copy(Converter::toCpp(pyobj)); else if (pyobj == Py_None) @@ -241,7 +241,7 @@ struct ValueTypeConverter } assert(false); } - return *reinterpret_cast(Wrapper::cppPointer(pyobj, SbkType())); + return *reinterpret_cast(Wrapper::cppPointer(reinterpret_cast(pyobj), SbkType())); } }; @@ -275,8 +275,8 @@ struct ObjectTypeConverter return 0; SbkObjectType* shiboType = reinterpret_cast(pyobj->ob_type); if (shiboType->mi_specialcast) - return (T*) shiboType->mi_specialcast(Wrapper::cppPointer(pyobj, SbkType()), reinterpret_cast(SbkType())); - return (T*) Wrapper::cppPointer(pyobj, SbkType()); + return (T*) shiboType->mi_specialcast(Wrapper::cppPointer(reinterpret_cast(pyobj), SbkType()), reinterpret_cast(SbkType())); + return (T*) Wrapper::cppPointer(reinterpret_cast(pyobj), SbkType()); } }; @@ -585,7 +585,7 @@ struct StdListConverter static StdList toCpp(PyObject* pyobj) { if (PyObject_TypeCheck(pyobj, SbkType())) - return *reinterpret_cast(Wrapper::cppPointer(pyobj, SbkType())); + return *reinterpret_cast(Wrapper::cppPointer(reinterpret_cast(pyobj), SbkType())); StdList result; for (int i = 0; i < PySequence_Size(pyobj); i++) { From f28d985527dd5674db0acbf3009f704b489eb870 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 10 Nov 2010 17:23:47 -0200 Subject: [PATCH 125/564] Fix the metaObject method written by the generator after the changed in libshiboken. --- generator/cppgenerator.cpp | 8 ++++---- libshiboken/conversions.h | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index e69ff3c7..68f90ce0 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -778,14 +778,14 @@ void CppGenerator::writeMetaObjectMethod(QTextStream& s, const AbstractMetaClass s << INDENT << "if (!m_metaObject) {\n"; { Indentation indentation(INDENT); - s << INDENT << "PyObject *pySelf = BindingManager::instance().retrieveWrapper(this);\n" - << INDENT << "void *typeData = Shiboken::getTypeUserData(reinterpret_cast(pySelf));" << endl + s << INDENT << "SbkObject* pySelf = BindingManager::instance().retrieveWrapper(this);\n" + << INDENT << "void* typeData = Shiboken::getTypeUserData(pySelf);" << endl << INDENT << "if (!typeData) {" << endl; { Indentation indentation2(INDENT); - s << INDENT << "m_metaObject = PySide::DynamicQMetaObject::createBasedOn(pySelf, pySelf->ob_type, &" + s << INDENT << "m_metaObject = PySide::DynamicQMetaObject::createBasedOn((PyObject*)pySelf, pySelf->ob_type, &" << metaClass->qualifiedCppName() << "::staticMetaObject);" << endl - << INDENT << "Shiboken::setTypeUserData(reinterpret_cast(pySelf), m_metaObject, PySide::deleteDynamicQMetaObject);" << endl; + << INDENT << "Shiboken::setTypeUserData(pySelf, m_metaObject, PySide::deleteDynamicQMetaObject);" << endl; } s << INDENT << "} else {" << endl; { diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index d8e28371..4d55ef0f 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -275,7 +275,9 @@ struct ObjectTypeConverter return 0; SbkObjectType* shiboType = reinterpret_cast(pyobj->ob_type); if (shiboType->mi_specialcast) - return (T*) shiboType->mi_specialcast(Wrapper::cppPointer(reinterpret_cast(pyobj), SbkType()), reinterpret_cast(SbkType())); + return (T*) shiboType->mi_specialcast( + Wrapper::cppPointer(reinterpret_cast(pyobj), SbkType()), + reinterpret_cast(SbkType())); return (T*) Wrapper::cppPointer(reinterpret_cast(pyobj), SbkType()); } }; From 9d3dfe4077857f1829ecdc6899ac4a383b9c32b7 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 10 Nov 2010 20:05:13 -0200 Subject: [PATCH 126/564] Added Shiboken::Wrapper::hasParentInfo function. Reviewer: Marcelo Lira Lauro Moura --- libshiboken/basewrapper.cpp | 5 +++++ libshiboken/basewrapper.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index af61aa00..47ec2749 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -666,6 +666,11 @@ void releaseOwnership(PyObject* pyObj) setSequenceOwnership(pyObj, false); } +bool hasParentInfo(SbkObject* pyObj) +{ + return pyObj->d->parentInfo; +} + void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType) { PyTypeObject* type = pyObj->ob_type; diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 0c85e907..98b9a4e0 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -203,6 +203,8 @@ LIBSHIBOKEN_API void getOwnership(SbkObject* pyObj); LIBSHIBOKEN_API void releaseOwnership(PyObject* pyObj); LIBSHIBOKEN_API void releaseOwnership(SbkObject* pyObj); +LIBSHIBOKEN_API bool hasParentInfo(SbkObject* pyObj); + /** * Get the C++ pointer of type \p desiredType from a Python object. */ From ed83e5ef62ad4ba04aea50ba1bd10ec4684fd07c Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Wed, 10 Nov 2010 18:33:00 -0300 Subject: [PATCH 127/564] Fix the fix that was previously reverted in d8e2d87f. Reviewed by Lauro Moura Reviewed by Luciano Wolf --- generator/overloaddata.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/generator/overloaddata.cpp b/generator/overloaddata.cpp index 9be972f1..29a1615f 100644 --- a/generator/overloaddata.cpp +++ b/generator/overloaddata.cpp @@ -147,6 +147,10 @@ void OverloadData::sortNextOverloads() OverloadSortData sortData; bool checkPyObject = false; int pyobjectIndex = 0; + bool checkQString = false; + int qstringIndex = 0; + bool checkQVariant = false; + int qvariantIndex = 0; // Primitive types that are not int, long, short, // char and their respective unsigned counterparts. @@ -172,6 +176,12 @@ void OverloadData::sortNextOverloads() if (!checkPyObject && getTypeName(ov->argType()).contains("PyObject")) { checkPyObject = true; pyobjectIndex = sortData.lastProcessedItemId(); + } else if (!checkQVariant && getTypeName(ov->argType()) == "QVariant") { + checkQVariant = true; + qvariantIndex = sortData.lastProcessedItemId(); + } else if (!checkQString && getTypeName(ov->argType()) == "QString") { + checkQString = true; + qstringIndex = sortData.lastProcessedItemId(); } foreach (const AbstractMetaType* instantiation, ov->argType()->instantiations()) { @@ -265,8 +275,15 @@ void OverloadData::sortNextOverloads() } /* Add dependency on PyObject, so its check is the last one (too generic) */ - if (checkPyObject && !targetTypeEntryName.contains("PyObject")) + if (checkPyObject && !targetTypeEntryName.contains("PyObject")) { graph.addEdge(sortData.map[targetTypeEntryName], pyobjectIndex); + } else if (checkQVariant && targetTypeEntryName != "QVariant") { + if (!graph.containsEdge(qvariantIndex, sortData.map[targetTypeEntryName])) // Avoid cyclic dependency. + graph.addEdge(sortData.map[targetTypeEntryName], qvariantIndex); + } else if (checkQString && ov->argType()->indirections() > 0 && targetTypeEntryName != "QString") { + if (!graph.containsEdge(qstringIndex, sortData.map[targetTypeEntryName])) // Avoid cyclic dependency. + graph.addEdge(sortData.map[targetTypeEntryName], qstringIndex); + } if (targetTypeEntry->isEnum()) { for (int i = 0; i < numPrimitives; ++i) { From d5bcf44bc644ed5c5fc983c454b2e4743cf4532f Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 11 Nov 2010 17:57:46 -0200 Subject: [PATCH 128/564] Do not generate return type check when the return type was modified to PyObject. --- generator/cppgenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 68f90ce0..dbe5479d 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -654,7 +654,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu if (invalidateReturn) s << INDENT << "bool invalidadeArg0 = " PYTHON_RETURN_VAR "->ob_refcnt == 1;" << endl; - if (func->type()) { + if (func->type() && func->typeReplaced(0) != "PyObject") { s << INDENT << "// Check return type" << endl; s << INDENT << "bool typeIsValid = "; QString desiredType; From 157c00f271b7a7cb963900e7b967070ac0e09c41 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 11 Nov 2010 17:58:40 -0200 Subject: [PATCH 129/564] Add operator= to AutoDecRef. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Renato Araújo Luciano Wolf --- libshiboken/autodecref.h | 47 +++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/libshiboken/autodecref.h b/libshiboken/autodecref.h index 20ed168d..85445951 100644 --- a/libshiboken/autodecref.h +++ b/libshiboken/autodecref.h @@ -37,34 +37,55 @@ class LIBSHIBOKEN_API AutoDecRef public: /** * AutoDecRef constructor. - * /param pyobj A borrowed reference to a Python object + * \param pyobj A borrowed reference to a Python object */ - explicit AutoDecRef(PyObject* pyobj) : m_pyobj(pyobj) {} + explicit AutoDecRef(PyObject* pyObj) : m_pyObj(pyObj) {} - ~AutoDecRef() { - Py_XDECREF(m_pyobj); + /// Decref the borrowed python reference + ~AutoDecRef() + { + Py_XDECREF(m_pyObj); } - inline bool isNull() const { return m_pyobj == 0; } + inline bool isNull() const { return m_pyObj == 0; } /// Returns the pointer of the Python object being held. - inline PyObject* object() { return m_pyobj; } - inline operator PyObject*() { return m_pyobj; } - inline operator PyTupleObject*() { return reinterpret_cast(m_pyobj); } - inline operator bool() const { return m_pyobj; } - inline PyObject* operator->() { return m_pyobj; } + inline PyObject* object() { return m_pyObj; } + inline operator PyObject*() { return m_pyObj; } + inline operator PyTupleObject*() { return reinterpret_cast(m_pyObj); } + inline operator bool() const { return m_pyObj; } + inline PyObject* operator->() { return m_pyObj; } template T cast() { - return reinterpret_cast(m_pyobj); + return reinterpret_cast(m_pyObj); + } + + /** + * Decref the current borrowed python reference and take the reference + * borrowed by \p other, so other.isNull() will return true. + */ + void operator=(AutoDecRef& other) + { + Py_XDECREF(m_pyObj); + m_pyObj = other.m_pyObj; + other.m_pyObj = 0; + } + + /** + * Decref the current borrowed python reference and borrow \p other. + */ + void operator=(PyObject* other) + { + Py_XDECREF(m_pyObj); + m_pyObj = other; } private: - PyObject* m_pyobj; + PyObject* m_pyObj; AutoDecRef(const AutoDecRef&); AutoDecRef& operator=(const AutoDecRef&); }; - } // namespace Shiboken #endif // AUTODECREF_H From 117a65fa1f9300151bb7dc5f33d4210135d615b7 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 18 Nov 2010 17:40:02 -0200 Subject: [PATCH 130/564] Replaces PySide::deleteDynamicQMetaObject by Shiboken::callCppDestructor Reviewer: Luciano Wolf Lauro Moura --- generator/cppgenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index dbe5479d..25584ce3 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -785,7 +785,7 @@ void CppGenerator::writeMetaObjectMethod(QTextStream& s, const AbstractMetaClass Indentation indentation2(INDENT); s << INDENT << "m_metaObject = PySide::DynamicQMetaObject::createBasedOn((PyObject*)pySelf, pySelf->ob_type, &" << metaClass->qualifiedCppName() << "::staticMetaObject);" << endl - << INDENT << "Shiboken::setTypeUserData(pySelf, m_metaObject, PySide::deleteDynamicQMetaObject);" << endl; + << INDENT << "Shiboken::setTypeUserData(pySelf, m_metaObject, &Shiboken::callCppDestructor);" << endl; } s << INDENT << "} else {" << endl; { From 76c2a25f4def623be9c4ab30f2bde36bfed7ae08 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Thu, 18 Nov 2010 09:25:23 -0300 Subject: [PATCH 131/564] Updated some tests to work with new API. --- tests/samplebinding/ownership_transference_test.py | 4 ++-- tests/samplebinding/typesystem_sample.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/samplebinding/ownership_transference_test.py b/tests/samplebinding/ownership_transference_test.py index 1a8682da..5097d1e0 100644 --- a/tests/samplebinding/ownership_transference_test.py +++ b/tests/samplebinding/ownership_transference_test.py @@ -48,8 +48,8 @@ def testOwnershipTransference(self): self.assertEqual(set(bb.objects()), set([o1, o2])) self.assertEqual(str(o1.objectName()), 'object1') self.assertEqual(str(o2.objectName()), 'object2') - self.assertEqual(sys.getrefcount(o1), o1_refcnt) - self.assertEqual(sys.getrefcount(o2), o2_refcnt) + self.assertEqual(sys.getrefcount(o1), o1_refcnt + 1) # PySide give +1 ref to object with c++ ownership + self.assertEqual(sys.getrefcount(o2), o2_refcnt + 1) o2 = bb.retrieveObjectType(o2_ticket) self.assertEqual(sys.getrefcount(o2), o2_refcnt) del bb diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index f6c049b8..37fa4742 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -178,9 +178,9 @@ if ((*it)->isLayoutType()) { ObjectTypeLayout* l = reinterpret_cast<ObjectTypeLayout*>(*it); reparent_layout_items(parent, %CONVERTTOPYTHON[ObjectTypeLayout*](l)); - Shiboken::setParent(layout, %CONVERTTOPYTHON[ObjectTypeLayout*](l)); + Wrapper::setParent(layout, %CONVERTTOPYTHON[ObjectTypeLayout*](l)); } else { - Shiboken::setParent(parent, %CONVERTTOPYTHON[ObjectType*](*it)); + Wrapper::setParent(parent, %CONVERTTOPYTHON[ObjectType*](*it)); } } } From e1ea3fe74afca099e7bba884256e0be0e6f7d200 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Thu, 18 Nov 2010 10:54:10 -0300 Subject: [PATCH 132/564] Rewrite parent control functions. Updated generator to new API. Fix bug #462 Reviewer: Luciano Wolf Hugo Parente Lima --- generator/cppgenerator.cpp | 29 ++- libshiboken/basewrapper.cpp | 408 ++++++++++++++++++++++----------- libshiboken/basewrapper.h | 63 +++-- libshiboken/basewrapper_p.h | 8 + libshiboken/bindingmanager.cpp | 91 +------- libshiboken/bindingmanager.h | 15 +- 6 files changed, 349 insertions(+), 265 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 25584ce3..239bd753 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -470,7 +470,8 @@ void CppGenerator::writeDestructorNative(QTextStream &s, const AbstractMetaClass { Indentation indentation(INDENT); s << wrapperName(metaClass) << "::~" << wrapperName(metaClass) << "()" << endl << '{' << endl; - s << INDENT << "BindingManager::instance().destroyWrapper(this);" << endl; + s << INDENT << "SbkObject* wrapper = BindingManager::instance().retrieveWrapper(this);" << endl; + s << INDENT << "Wrapper::destroy(wrapper);" << endl; s << '}' << endl; } @@ -523,6 +524,14 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu return; } + //Write declaration/native injected code + if (func->hasInjectedCode()) { + CodeSnipList snips = func->injectedCodeSnips(); + const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); + writeCodeSnips(s, snips, CodeSnip::Declaration, TypeSystem::NativeCode, func, lastArg); + s << endl; + } + s << INDENT << "Shiboken::GilState gil;" << endl; s << INDENT << "Shiboken::AutoDecRef py_override(BindingManager::instance().getOverride(this, \""; @@ -542,7 +551,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu if (func->isAbstract()) { s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '"; s << func->ownerClass()->name() << '.' << func->name(); - s << "()' not implemented.\");" << endl; + s << "()' not implemented.\");" << endl; s << INDENT << "return "; if (func->type()) { s << defaultReturnExpr; @@ -731,7 +740,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu if (invalidateReturn) { s << INDENT << "if (invalidadeArg0)" << endl; Indentation indentation(INDENT); - s << INDENT << "BindingManager::instance().invalidateWrapper(" << PYTHON_RETURN_VAR ".object());" << endl; + s << INDENT << "Wrapper::invalidate(" << PYTHON_RETURN_VAR ".object());" << endl; } foreach (FunctionModification funcMod, func->modifications()) { @@ -739,7 +748,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu if (argMod.resetAfterUse) { s << INDENT << "if (invalidadeArg" << argMod.index << ")" << endl; Indentation indentation(INDENT); - s << INDENT << "BindingManager::instance().invalidateWrapper(PyTuple_GET_ITEM(pyargs, "; + s << INDENT << "Wrapper::invalidate(PyTuple_GET_ITEM(pyargs, "; s << (argMod.index - 1) << "));" << endl; } } @@ -2121,15 +2130,15 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f s << INDENT; if (arg_mod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::TargetLangOwnership) { - s << "Shiboken::Wrapper::getOwnership(" << pyArgName << ");"; + s << "Wrapper::getOwnership(" << pyArgName << ");"; } else if (wrappedClass->hasVirtualDestructor()) { if (arg_mod.index == 0) { - s << "Shiboken::Wrapper::releaseOwnership(" PYTHON_RETURN_VAR ");"; + s << "Wrapper::releaseOwnership(" PYTHON_RETURN_VAR ");"; } else { - s << "BindingManager::instance().transferOwnershipToCpp(" << pyArgName << ");"; + s << "Wrapper::releaseOwnership(" << pyArgName << ");"; } } else { - s << "BindingManager::instance().invalidateWrapper(" << pyArgName << ");"; + s << "Wrapper::invalidate(" << pyArgName << ");"; } s << endl; } @@ -3798,7 +3807,7 @@ bool CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMeta else childVariable = usePyArgs ? "pyargs["+QString::number(childIndex-1)+"]" : "arg"; - s << INDENT << "Shiboken::setParent(" << parentVariable << ", " << childVariable << ");\n"; + s << INDENT << "Wrapper::setParent(" << parentVariable << ", " << childVariable << ");\n"; return true; } @@ -3832,7 +3841,7 @@ void CppGenerator::writeReturnValueHeuristics(QTextStream& s, const AbstractMeta } if (type->isQObject() || type->isObject() || type->isValuePointer()) - s << INDENT << "Shiboken::setParent(" << self << ", " PYTHON_RETURN_VAR ");" << endl; + s << INDENT << "Wrapper::setParent(" << self << ", " PYTHON_RETURN_VAR ");" << endl; } void CppGenerator::writeHashFunction(QTextStream& s, const AbstractMetaClass* metaClass) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 47ec2749..37d1282a 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -23,12 +23,13 @@ #include "basewrapper.h" #include "basewrapper_p.h" #include "sbkenum.h" -#include -#include #include "autodecref.h" #include "typeresolver.h" +#include "gilstate.h" #include #include +#include +#include extern "C" { @@ -163,8 +164,8 @@ void SbkDeallocWrapper(PyObject* pyObj) if (sbkObj->weakreflist) PyObject_ClearWeakRefs(pyObj); - Shiboken::BindingManager::instance().releaseWrapper(sbkObj); - if (sbkObj->d->hasOwnership) { + // If I have ownership and is valid delete C++ pointer + if (sbkObj->d->hasOwnership && sbkObj->d->validCppObject) { SbkObjectType* sbkType = reinterpret_cast(pyObj->ob_type); if (sbkType->is_multicpp) { Shiboken::DtorCallerVisitor visitor(sbkObj); @@ -174,26 +175,17 @@ void SbkDeallocWrapper(PyObject* pyObj) } } - if (sbkObj->d->parentInfo) - Shiboken::destroyParentInfo(sbkObj); - - Shiboken::clearReferences(sbkObj); - - Py_XDECREF(sbkObj->ob_dict); - delete[] sbkObj->d->cptr; - sbkObj->d->cptr = 0; - delete sbkObj->d; - Py_TYPE(pyObj)->tp_free(pyObj); + Shiboken::Wrapper::deallocData(sbkObj); } void SbkDeallocWrapperWithPrivateDtor(PyObject* self) { - if (((SbkObject *)self)->weakreflist) + SbkObject* sbkObj = reinterpret_cast(self); + if (sbkObj->weakreflist) PyObject_ClearWeakRefs(self); - Shiboken::BindingManager::instance().releaseWrapper(reinterpret_cast(self)); - Shiboken::clearReferences(reinterpret_cast(self)); - self->ob_type->tp_free(self); + Shiboken::BindingManager::instance().releaseWrapper(sbkObj); + Shiboken::Wrapper::deallocData(sbkObj); } void SbkObjectTypeDealloc(PyObject* pyObj) @@ -275,111 +267,6 @@ namespace Shiboken static void incRefPyObject(PyObject* pyObj); static void decRefPyObjectList(const std::list &pyObj); -void removeParent(SbkObject* child) -{ - ParentInfo* pInfo = child->d->parentInfo; - if (!pInfo || !pInfo->parent) - return; - - ChildrenList& oldBrothers = pInfo->parent->d->parentInfo->children; - oldBrothers.remove(child); - pInfo->parent = 0; - - if (pInfo->hasWrapperRef) { - Py_DECREF(child); - pInfo->hasWrapperRef = false; - } - Py_DECREF(child); -} - -void setParent(PyObject* parent, PyObject* child) -{ - if (!child || child == Py_None || child == parent) - return; - - /* - * setParent is recursive when the child is a native Python sequence, i.e. objects not binded by Shiboken - * like tuple and list. - * - * This "limitation" exists to fix the following problem: A class multiple inherits QObject and QString, - * so if you pass this class to someone that takes the ownership, we CAN'T enter in this if, but hey! QString - * follows the sequence protocol. - */ - if (PySequence_Check(child) && !isShibokenType(child)) { - Shiboken::AutoDecRef seq(PySequence_Fast(child, 0)); - for (int i = 0, max = PySequence_Size(seq); i < max; ++i) - setParent(parent, PySequence_Fast_GET_ITEM(seq.object(), i)); - return; - } - - bool parentIsNull = !parent || parent == Py_None; - SbkObject* parent_ = reinterpret_cast(parent); - SbkObject* child_ = reinterpret_cast(child); - - if (!parentIsNull) { - if (!parent_->d->parentInfo) - parent_->d->parentInfo = new ParentInfo; - // do not re-add a child - ChildrenList& children = parent_->d->parentInfo->children; - if (std::find(children.begin(), children.end(), child_) != children.end()) - return; - } - - ParentInfo* pInfo = child_->d->parentInfo; - bool hasAnotherParent = pInfo && pInfo->parent && pInfo->parent != parent_; - - //Avoid destroy child during reparent operation - Py_INCREF(child); - - // check if we need to remove this child from the old parent - if (parentIsNull || hasAnotherParent) - removeParent(child_); - - // Add the child to the new parent - pInfo = child_->d->parentInfo; - if (!parentIsNull) { - if (!pInfo) - pInfo = child_->d->parentInfo = new ParentInfo; - pInfo->parent = parent_; - parent_->d->parentInfo->children.push_back(child_); - Py_INCREF(child_); - } - - Py_DECREF(child); -} - -static void _destroyParentInfo(SbkObject* obj, bool removeFromParent) -{ - ParentInfo* pInfo = obj->d->parentInfo; - if (removeFromParent && pInfo && pInfo->parent) - removeParent(obj); - - if (pInfo) { - ChildrenList::iterator it = pInfo->children.begin(); - for (; it != pInfo->children.end(); ++it) { - SbkObject*& child = *it; - - // keep this, the wrapper still alive - if (!obj->d->containsCppWrapper && child->d->containsCppWrapper && child->d->parentInfo) { - child->d->parentInfo->parent = 0; - child->d->parentInfo->hasWrapperRef = true; - child->d->hasOwnership = false; - } else { - _destroyParentInfo(child, false); - Py_DECREF(child); - } - } - delete pInfo; - obj->d->parentInfo = 0; - } -} - -void destroyParentInfo(SbkObject* obj, bool removeFromParent) -{ - BindingManager::instance().destroyWrapper(obj); - _destroyParentInfo(obj, removeFromParent); -} - void walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visitor) { PyObject* bases = currentType->tp_bases; @@ -611,20 +498,45 @@ static void decRefPyObjectList(const std::list& lst) } } +namespace Wrapper +{ + static void setSequenceOwnership(PyObject* pyObj, bool owner) { if (PySequence_Check(pyObj)) { std::list objs = splitPyObject(pyObj); std::list::const_iterator it = objs.begin(); - for(; it != objs.end(); ++it) - (*it)->d->hasOwnership = owner; + for(; it != objs.end(); ++it) { + if (owner) + getOwnership(*it); + else + releaseOwnership(*it); + } } else if (isShibokenType(pyObj)) { - reinterpret_cast(pyObj)->d->hasOwnership = owner; + if (owner) + getOwnership(reinterpret_cast(pyObj)); + else + releaseOwnership(reinterpret_cast(pyObj)); } } -namespace Wrapper + +static void _destroyParentInfo(SbkObject* obj, bool keepReference) { + ParentInfo* pInfo = obj->d->parentInfo; + if (pInfo) { + while(!pInfo->children.empty()) { + SbkObject* first = pInfo->children.front(); + // Mark child as invalid + Shiboken::Wrapper::invalidate(first); + removeParent(first, false, keepReference); + } + removeParent(obj, false); + delete pInfo; + obj->d->parentInfo = 0; + } +} + void setValidCpp(SbkObject* pyObj, bool value) { @@ -646,9 +558,23 @@ bool hasOwnership(SbkObject* pyObj) return pyObj->d->hasOwnership; } -void getOwnership(SbkObject* pyObj) +void getOwnership(SbkObject* self) { - pyObj->d->hasOwnership = true; + // skip if already have the ownership + if (self->d->hasOwnership) + return; + + // skip if this object has parent + if (self->d->parentInfo && self->d->parentInfo->parent) + return; + + // Get back the ownership + self->d->hasOwnership = true; + + if (self->d->containsCppWrapper) + Py_DECREF((PyObject*) self); // Remove extra ref + else + makeValid(self); // Make the object valid again } void getOwnership(PyObject* pyObj) @@ -656,14 +582,78 @@ void getOwnership(PyObject* pyObj) setSequenceOwnership(pyObj, true); } -void releaseOwnership(SbkObject* pyObj) +void releaseOwnership(SbkObject* self) +{ + // skip if the ownership have already moved to c++ + if (!self->d->hasOwnership) + return; + + // remove object ownership + self->d->hasOwnership = false; + + // If We have control over object life + if (self->d->containsCppWrapper) + Py_INCREF((PyObject*) self); // keep the python object alive until the wrapper destructor call + else + invalidate(self); // If I do not know when this object will die We need to invalidate this to avoid use after +} + +void releaseOwnership(PyObject* self) +{ + setSequenceOwnership(self, false); +} + +void invalidate(PyObject* pyobj) { - pyObj->d->hasOwnership = false; + std::list objs = splitPyObject(pyobj); + std::list::const_iterator it = objs.begin(); + for(; it != objs.end(); it++) + invalidate(*it); } -void releaseOwnership(PyObject* pyObj) +void invalidate(SbkObject* self) { - setSequenceOwnership(pyObj, false); + // Skip if this object not is a valid object + if (!self || ((PyObject*)self == Py_None)) + return; + + if (!self->d->containsCppWrapper) { + self->d->validCppObject = false; // Mark object as invalid only if this is not a wrapper class + BindingManager::instance().releaseWrapper(self); + } + + // If it is a parent invalidate all children. + if (self->d->parentInfo) { + // Create a copy because this list can be changed during the process + ChildrenList copy = self->d->parentInfo->children; + ChildrenList::iterator it = copy.begin(); + + for (; it != copy.end(); ++it) { + // invalidate the child + invalidate(*it); + + // if the parent not is a wrapper class, then remove children from him, because We do not know when this object will be destroyed + if (!self->d->validCppObject) + removeParent(*it, true, true); + } + } +} + +void makeValid(SbkObject* self) +{ + // Skip if this object not is a valid object + if (!self || ((PyObject*)self == Py_None)) + return; + + // Mark object as invalid only if this is not a wrapper class + self->d->validCppObject = true; + + // If it is a parent make all children valid + if (self->d->parentInfo) { + ChildrenList::iterator it = self->d->parentInfo->children.begin(); + for (; it != self->d->parentInfo->children.end(); ++it) + makeValid(*it); + } } bool hasParentInfo(SbkObject* pyObj) @@ -732,6 +722,158 @@ PyObject* newObject(SbkObjectType* instanceType, return reinterpret_cast(self); } +void destroy(SbkObject* self) +{ + // Skip if this is called with NULL pointer this can happen in derived classes + if (!self) + return; + + // This can be called in c++ side + Shiboken::GilState gil; + + // We will marks this object as invalid because this function will be called from wrapper destructor + // If The object has ownership and this was destroyed then is necessary invalidate to avoid future used by Python + self->d->validCppObject = false; + + // Remove all references attached to this object + clearReferences(self); + + // Remove from BindinManager + Shiboken::BindingManager::instance().releaseWrapper(self); + + // Remove the object from parent control + + // Verify if this object has parent + bool hasParent = (self->d->parentInfo && self->d->parentInfo->parent); + + if (self->d->parentInfo) { + // Check for children information and make all invalid if they exists + _destroyParentInfo(self, true); + // If this object has parent then the pyobject can be invalid now, because we remove the last ref after remove from parent + } + + //if !hasParent this object could still alive + if (!hasParent && self->d->containsCppWrapper && !self->d->hasOwnership) { + // Remove extra ref used by c++ object this will case the pyobject destruction + // This can cause the object death + Py_DECREF((PyObject*)self); + } + // After this point the object can be death do not use the self pointer bellow +} + +void removeParent(SbkObject* child, bool giveOwnershipBack, bool keepReference) +{ + ParentInfo* pInfo = child->d->parentInfo; + if (!pInfo || !pInfo->parent) { + return; + } + + ChildrenList& oldBrothers = pInfo->parent->d->parentInfo->children; + // Verify if this child is part of parent list + ChildrenList::iterator iChild = std::find(oldBrothers.begin(), oldBrothers.end(), child); + if (iChild == oldBrothers.end()) + return; + + oldBrothers.erase(iChild); + + pInfo->parent = 0; + + // This will keep the wrapper reference, will wait for wrapper destruction to remove that + if (keepReference && child->d->containsCppWrapper) + return; + + // Transfer ownership back to Python + child->d->hasOwnership = giveOwnershipBack; + + // Remove parent ref + Py_DECREF(child); +} + +void setParent(PyObject* parent, PyObject* child) +{ + if (!child || child == Py_None || child == parent) + return; + + /* + * setParent is recursive when the child is a native Python sequence, i.e. objects not binded by Shiboken + * like tuple and list. + * + * This "limitation" exists to fix the following problem: A class multiple inherits QObject and QString, + * so if you pass this class to someone that takes the ownership, we CAN'T enter in this if, but hey! QString + * follows the sequence protocol. + */ + if (PySequence_Check(child) && !isShibokenType(child)) { + Shiboken::AutoDecRef seq(PySequence_Fast(child, 0)); + for (int i = 0, max = PySequence_Size(seq); i < max; ++i) + setParent(parent, PySequence_Fast_GET_ITEM(seq.object(), i)); + return; + } + + bool parentIsNull = !parent || parent == Py_None; + SbkObject* parent_ = reinterpret_cast(parent); + SbkObject* child_ = reinterpret_cast(child); + + if (!parentIsNull) { + if (!parent_->d->parentInfo) + parent_->d->parentInfo = new ParentInfo; + // do not re-add a child + ChildrenList& children = parent_->d->parentInfo->children; + if (std::find(children.begin(), children.end(), child_) != children.end()) + return; + } + + ParentInfo* pInfo = child_->d->parentInfo; + bool hasAnotherParent = pInfo && pInfo->parent && pInfo->parent != parent_; + + //Avoid destroy child during reparent operation + Py_INCREF(child); + + // check if we need to remove this child from the old parent + if (parentIsNull || hasAnotherParent) + removeParent(child_); + + // Add the child to the new parent + pInfo = child_->d->parentInfo; + if (!parentIsNull) { + if (!pInfo) + pInfo = child_->d->parentInfo = new ParentInfo; + + pInfo->parent = parent_; + parent_->d->parentInfo->children.push_back(child_); + + // Add Parent ref + Py_INCREF(child_); + + // Remove ownership + child_->d->hasOwnership = false; + } + + // Remove previous safe ref + Py_DECREF(child); +} + +void deallocData(SbkObject* self) +{ + // Make cleanup if this is not a wrapper otherwise this will be done on wrapper destructor + if(!self->d->containsCppWrapper) { + removeParent(self); + + if (self->d->parentInfo) + _destroyParentInfo(self, true); + + clearReferences(self); + + // Remove from BindinManager + Shiboken::BindingManager::instance().releaseWrapper(self); + } + + Py_XDECREF(self->ob_dict); + delete[] self->d->cptr; + self->d->cptr = 0; + delete self->d; + Py_TYPE(self)->tp_free(self); +} + } // namespace Wrapper } // namespace Shiboken diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 98b9a4e0..f723a7a9 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -113,26 +113,6 @@ namespace Shiboken */ LIBSHIBOKEN_API void initShiboken(); -/** -* Set the parent of \p child to \p parent. -* When an object dies, all their children, granchildren, etc, are tagged as invalid. -* \param parent the parent object, if null, the child will have no parents. -* \param child the child. -*/ -LIBSHIBOKEN_API void setParent(PyObject* parent, PyObject* child); - -/** -* Remove this child from their parent, if any. -* \param child the child. -*/ -LIBSHIBOKEN_API void removeParent(SbkObject* child); - -/** -* \internal This is an internal function called by SbkBaseWrapper_Dealloc, it's exported just for techinical reasons. -* \note Do not call this function inside your bindings. -*/ -LIBSHIBOKEN_API void destroyParentInfo(SbkObject* obj, bool removeFromParent = true); - /** * Returns true if the object is an instance of a type created by the Shiboken generator. */ @@ -215,9 +195,50 @@ LIBSHIBOKEN_API void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType); */ LIBSHIBOKEN_API bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr); -/// Returns false and sets a Python RuntimeError if the Python wrapper is not marked as valid. +/** + * Returns false and sets a Python RuntimeError if the Python wrapper is not marked as valid. + */ LIBSHIBOKEN_API bool isValid(PyObject* wrapper); +/** +* Set the parent of \p child to \p parent. +* When an object dies, all their children, granchildren, etc, are tagged as invalid. +* \param parent the parent object, if null, the child will have no parents. +* \param child the child. +*/ +LIBSHIBOKEN_API void setParent(PyObject* parent, PyObject* child); + +/** +* Remove this child from their parent, if any. +* \param child the child. +*/ +LIBSHIBOKEN_API void removeParent(SbkObject* child, bool giveOwnershipBack = true, bool keepReferenc = false); + +/** +* \internal This is an internal function called by SbkBaseWrapper_Dealloc, it's exported just for techinical reasons. +* \note Do not call this function inside your bindings. +*/ +LIBSHIBOKEN_API void destroyParentInfo(SbkObject* obj, bool removeFromParent = true); + +/** + * Mark the object as invalid + */ +LIBSHIBOKEN_API void invalidate(SbkObject* self); + +/** + * Help function can be used to invalida a sequence of object + **/ +LIBSHIBOKEN_API void invalidate(PyObject* pyobj); + +/** + * Make the object valid again + */ +LIBSHIBOKEN_API void makeValid(SbkObject* self); + +/** + * Destroy any data in Shiboken structure and c++ pointer if the pyboject has the ownership + **/ +LIBSHIBOKEN_API void destroy(SbkObject* self); } // namespace Wrapper diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h index 6cd4b31f..748ce2dc 100644 --- a/libshiboken/basewrapper_p.h +++ b/libshiboken/basewrapper_p.h @@ -196,6 +196,14 @@ inline std::list getCppBaseClasses(PyTypeObject* baseType) */ void clearReferences(SbkObject* self); +namespace Wrapper +{ +/** + * Destroy internal data + **/ +void deallocData(SbkObject* self); +} // namespace Wrapper + } // namespace Shiboken #endif diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index 183c0c05..b56cceed 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -147,8 +147,9 @@ BindingManager::~BindingManager() /* Cleanup hanging references. We just invalidate them as when * the BindingManager is being destroyed the interpreter is alredy * shutting down. */ - while (!m_d->wrapperMapper.empty()) - invalidateWrapper(m_d->wrapperMapper.begin()->second); + while (!m_d->wrapperMapper.empty()) { + Wrapper::destroy(m_d->wrapperMapper.begin()->second); + } assert(m_d->wrapperMapper.size() == 0); delete m_d; } @@ -162,6 +163,7 @@ bool BindingManager::hasWrapper(const void* cptr) { return m_d->wrapperMapper.count(cptr); } + void BindingManager::registerWrapper(SbkObject* pyObj, void* cptr) { SbkObjectType* instanceType = reinterpret_cast(pyObj->ob_type); @@ -248,91 +250,6 @@ PyObject* BindingManager::getOverride(const void* cptr, const char* methodName) return 0; } - -void BindingManager::invalidateWrapper(PyObject* pyobj) -{ - std::list objs = splitPyObject(pyobj); - std::list::const_iterator it = objs.begin(); - for(; it != objs.end(); it++) - invalidateWrapper(*it); -} - -void BindingManager::invalidateWrapper(SbkObject* wrapper) -{ - if (!wrapper || ((PyObject*)wrapper == Py_None) || !wrapper->d->validCppObject) - return; - - GilState gil; // lock the gil to assure no one is changing the value of m_d->destroying - - // skip this if the object is a wrapper class and this is not a destructor call - if (wrapper->d->containsCppWrapper && !m_d->destroying) { - ParentInfo* pInfo = wrapper->d->parentInfo; - // this meaning the object has a extra ref and we will remove this now - if (pInfo && pInfo->hasWrapperRef) { - delete pInfo; - wrapper->d->parentInfo = 0; - Py_XDECREF((PyObject*) wrapper); - } - return; - } - - wrapper->d->validCppObject = false; - wrapper->d->hasOwnership = false; - - // If it is a parent invalidate all children. - if (wrapper->d->parentInfo) { - ChildrenList::iterator it = wrapper->d->parentInfo->children.begin(); - bool parentDestroying = m_d->destroying; - m_d->destroying = false; - for (; it != wrapper->d->parentInfo->children.end(); ++it) - invalidateWrapper(*it); - m_d->destroying = parentDestroying; - } - - releaseWrapper(wrapper); -} - -void BindingManager::invalidateWrapper(const void* cptr) -{ - WrapperMap::iterator iter = m_d->wrapperMapper.find(cptr); - if (iter != m_d->wrapperMapper.end()) - invalidateWrapper(iter->second); -} - -void BindingManager::destroyWrapper(const void* cptr) -{ - WrapperMap::iterator iter = m_d->wrapperMapper.find(cptr); - if (iter != m_d->wrapperMapper.end()) - destroyWrapper(reinterpret_cast(iter->second)); -} - -void BindingManager::destroyWrapper(SbkObject* wrapper) -{ - GilState gil; - m_d->destroying = true; - invalidateWrapper(wrapper); - m_d->destroying = false; -} - -void BindingManager::transferOwnershipToCpp(PyObject* wrapper) -{ - std::list objs = splitPyObject(wrapper); - std::list::const_iterator it = objs.begin(); - for(; it != objs.end(); it++) - transferOwnershipToCpp(*it); -} - -void BindingManager::transferOwnershipToCpp(SbkObject* wrapper) -{ - if (wrapper->d->parentInfo) - Shiboken::removeParent(wrapper); - - if (wrapper->d->containsCppWrapper) - wrapper->d->hasOwnership = false; - else - invalidateWrapper(wrapper); -} - void BindingManager::addClassInheritance(SbkObjectType* parent, SbkObjectType* child) { m_d->classHierarchy.addEdge(parent, child); diff --git a/libshiboken/bindingmanager.h b/libshiboken/bindingmanager.h index c1926e5e..b6d4ac42 100644 --- a/libshiboken/bindingmanager.h +++ b/libshiboken/bindingmanager.h @@ -42,26 +42,13 @@ class LIBSHIBOKEN_API BindingManager void registerWrapper(SbkObject* pyObj, void* cptr); void releaseWrapper(SbkObject* wrapper); + SbkObject* retrieveWrapper(const void* cptr); PyObject* getOverride(const void* cptr, const char* methodName); - /// Invalidate the Python wrapper and removes the relations from C++ pointers to the Python wrapper. - void invalidateWrapper(SbkObject* wrapper); - /// Convenience method to call invalidateWrapper with a properly cast SbkBaseWrapper. - void invalidateWrapper(PyObject* wrapper); - /// Convenience method to invalidate the Python wrapper for a C++ wrapped object. Do nothing if C++ pointer has no Python wrapper. - void invalidateWrapper(const void* cptr); - - /// Transfers the ownership of a Python wrapper to C++. - void transferOwnershipToCpp(SbkObject* wrapper); - /// Convenience method to call transferOwnershipToCpp with a properly cast SbkBaseWrapper. - void transferOwnershipToCpp(PyObject* wrapper); void addClassInheritance(SbkObjectType* parent, SbkObjectType* child); SbkObjectType* resolveType(void* cptr, SbkObjectType* type); - /// Called by wrapper destructor - void destroyWrapper(const void* cptr); - void destroyWrapper(SbkObject* wrapper); std::set getAllPyObjects(); private: ~BindingManager(); From 36b1807b8c5fe75faf87a593ac0e1d7e9ac8b887 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 19 Nov 2010 16:56:22 -0200 Subject: [PATCH 133/564] Rename SbkBaseType back to SbkObjectType. --- generator/cppgenerator.cpp | 24 +++++------ generator/headergenerator.cpp | 4 +- libshiboken/basewrapper.cpp | 74 +++++++++++++++++----------------- libshiboken/basewrapper.h | 50 +++++++++++------------ libshiboken/basewrapper_p.h | 18 ++++----- libshiboken/bindingmanager.cpp | 22 +++++----- libshiboken/bindingmanager.h | 6 +-- libshiboken/conversions.h | 10 ++--- 8 files changed, 104 insertions(+), 104 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 537c658f..d1ebf773 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -866,8 +866,8 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun s << INDENT << "SbkObject* sbkSelf = reinterpret_cast(self);" << endl; if (metaClass->isAbstract() || metaClass->baseClassNames().size() > 1) { - s << INDENT << "SbkBaseType* type = reinterpret_cast(self->ob_type);" << endl; - s << INDENT << "SbkBaseType* myType = reinterpret_cast(" << cpythonTypeNameExt(metaClass->typeEntry()) << ");" << endl; + s << INDENT << "SbkObjectType* type = reinterpret_cast(self->ob_type);" << endl; + s << INDENT << "SbkObjectType* myType = reinterpret_cast(" << cpythonTypeNameExt(metaClass->typeEntry()) << ");" << endl; } if (metaClass->isAbstract()) { @@ -2224,12 +2224,12 @@ void CppGenerator::writeMultipleInheritanceInitializerFunction(QTextStream& s, c void CppGenerator::writeSpecialCastFunction(QTextStream& s, const AbstractMetaClass* metaClass) { QString className = metaClass->qualifiedCppName(); - s << "static void* " << cpythonSpecialCastFunctionName(metaClass) << "(void* obj, SbkBaseType* desiredType)\n"; + s << "static void* " << cpythonSpecialCastFunctionName(metaClass) << "(void* obj, SbkObjectType* desiredType)\n"; s << "{\n"; s << INDENT << className << "* me = reinterpret_cast<" << className << "*>(obj);\n"; bool firstClass = true; foreach (const AbstractMetaClass* baseClass, getAllAncestors(metaClass)) { - s << INDENT << (!firstClass ? "else " : "") << "if (desiredType == reinterpret_cast(" << cpythonTypeNameExt(baseClass->typeEntry()) << "))\n"; + s << INDENT << (!firstClass ? "else " : "") << "if (desiredType == reinterpret_cast(" << cpythonTypeNameExt(baseClass->typeEntry()) << "))\n"; Indentation indent(INDENT); s << INDENT << "return static_cast<" << baseClass->qualifiedCppName() << "*>(me);\n"; firstClass = false; @@ -2281,7 +2281,7 @@ void CppGenerator::writeExtendedToCppFunction(QTextStream& s, const TypeEntry* e void CppGenerator::writeExtendedConverterInitialization(QTextStream& s, const TypeEntry* externalType, const QList& conversions) { s << INDENT << "// Extended implicit conversions for " << externalType->targetLangPackage() << '.' << externalType->name() << endl; - s << INDENT << "shiboType = reinterpret_cast("; + s << INDENT << "shiboType = reinterpret_cast("; s << cppApiVariableName(externalType->targetLangPackage()) << '['; s << getTypeIndexVariableName(externalType) << "]);" << endl; s << INDENT << "Shiboken::BaseType::setExternalIsConvertibleFunction(shiboType, " << extendedIsConvertibleFunctionName(externalType) << ");" << endl; @@ -2414,7 +2414,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* s << "// Class Definition -----------------------------------------------" << endl; s << "extern \"C\" {" << endl; - s << "static SbkBaseType " << className + "_Type" << " = { { {" << endl; + s << "static SbkObjectType " << className + "_Type" << " = { { {" << endl; s << INDENT << "PyObject_HEAD_INIT(&SbkBaseType_Type)" << endl; s << INDENT << "/*ob_size*/ 0," << endl; s << INDENT << "/*tp_name*/ \"" << metaClass->fullName() << "\"," << endl; @@ -3234,7 +3234,7 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m if (miClass == metaClass) s << INDENT << "func = " << multipleInheritanceInitializerFunctionName(miClass) << ";" << endl; else - s << INDENT << "func = Shiboken::BaseType::getMultipleIheritanceFunction(reinterpret_cast(" << cpythonTypeNameExt(miClass->typeEntry()) << "));" << endl; + s << INDENT << "func = Shiboken::BaseType::getMultipleIheritanceFunction(reinterpret_cast(" << cpythonTypeNameExt(miClass->typeEntry()) << "));" << endl; s << INDENT << "Shiboken::BaseType::setMultipleIheritanceFunction(&" << cpythonTypeName(metaClass) << ", func);" << endl; s << INDENT << "Shiboken::BaseType::setCastFunction(&" << cpythonTypeName(metaClass) << ", &" << cpythonSpecialCastFunctionName(metaClass) << ");" << endl; @@ -3264,7 +3264,7 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m s << INDENT << "Shiboken::BaseType::setTypeDiscoveryFunction(&" << cpythonTypeName(metaClass) << ", &" << cpythonBaseName(metaClass) << "_typeDiscovery);" << endl; s << INDENT << "Shiboken::BindingManager& bm = Shiboken::BindingManager::instance();" << endl; foreach (const AbstractMetaClass* base, baseClasses) { - s << INDENT << "bm.addClassInheritance(reinterpret_cast(" << cpythonTypeNameExt(base->typeEntry()) << "), &" << cpythonTypeName(metaClass) << ");" << endl; + s << INDENT << "bm.addClassInheritance(reinterpret_cast(" << cpythonTypeNameExt(base->typeEntry()) << "), &" << cpythonTypeName(metaClass) << ");" << endl; } } s << endl; @@ -3345,7 +3345,7 @@ void CppGenerator::writeTypeDiscoveryFunction(QTextStream& s, const AbstractMeta { QString polymorphicExpr = metaClass->typeEntry()->polymorphicIdValue(); - s << "static SbkBaseType* " << cpythonBaseName(metaClass) << "_typeDiscovery(void* cptr, SbkBaseType* instanceType)\n{" << endl; + s << "static SbkObjectType* " << cpythonBaseName(metaClass) << "_typeDiscovery(void* cptr, SbkObjectType* instanceType)\n{" << endl; if (!metaClass->baseClass()) { s << INDENT << "TypeResolver* typeResolver = TypeResolver::get(typeid(*reinterpret_cast<" @@ -3353,7 +3353,7 @@ void CppGenerator::writeTypeDiscoveryFunction(QTextStream& s, const AbstractMeta s << INDENT << "if (typeResolver)" << endl; { Indentation indent(INDENT); - s << INDENT << "return reinterpret_cast(typeResolver->pythonType());" << endl; + s << INDENT << "return reinterpret_cast(typeResolver->pythonType());" << endl; } } else if (!polymorphicExpr.isEmpty()) { polymorphicExpr = polymorphicExpr.replace("%1", " reinterpret_cast<"+metaClass->qualifiedCppName()+"*>(cptr)"); @@ -3368,7 +3368,7 @@ void CppGenerator::writeTypeDiscoveryFunction(QTextStream& s, const AbstractMeta if (ancestor->baseClass()) continue; if (ancestor->isPolymorphic()) { - s << INDENT << "if (instanceType == reinterpret_cast(Shiboken::SbkType<" + s << INDENT << "if (instanceType == reinterpret_cast(Shiboken::SbkType<" << ancestor->qualifiedCppName() << " >()) && dynamic_cast<" << metaClass->qualifiedCppName() << "*>(reinterpret_cast<"<< ancestor->qualifiedCppName() << "*>(cptr)))" << endl; Indentation indent(INDENT); @@ -3689,7 +3689,7 @@ void CppGenerator::finishGeneration() if (!extendedConverters.isEmpty()) { s << INDENT << "// Initialize extended Converters" << endl; - s << INDENT << "SbkBaseType* shiboType;" << endl << endl; + s << INDENT << "SbkObjectType* shiboType;" << endl << endl; } foreach (const TypeEntry* externalType, extendedConverters.keys()) { writeExtendedConverterInitialization(s, externalType, extendedConverters[externalType]); diff --git a/generator/headergenerator.cpp b/generator/headergenerator.cpp index 590aea38..f1b8086d 100644 --- a/generator/headergenerator.cpp +++ b/generator/headergenerator.cpp @@ -434,7 +434,7 @@ void HeaderGenerator::finishGeneration() s << INDENT << metaClass->qualifiedCppName() << "* value = const_cast<" << metaClass->qualifiedCppName() << "* >(cppobj);" << endl; s << INDENT << "if (!isExactType)" << endl; s << INDENT << INDENT << "typeName = typeid(*value).name();" << endl; - s << INDENT << "PyObject* pyObj = Shiboken::Wrapper::newObject(reinterpret_cast(SbkType<" << metaClass->qualifiedCppName() << " >())," + s << INDENT << "PyObject* pyObj = Shiboken::Wrapper::newObject(reinterpret_cast(SbkType<" << metaClass->qualifiedCppName() << " >())," << "value, hasOwnership, isExactType, typeName);" << endl; s << INDENT << "PySide::Signal::updateSourceObject(pyObj);" << endl; s << INDENT << "return pyObj;" << endl; @@ -531,7 +531,7 @@ void HeaderGenerator::writeTypeConverterImpl(QTextStream& s, const TypeEntry* ty } - s << INDENT << "SbkBaseType* shiboType = reinterpret_cast(SbkType<"; + s << INDENT << "SbkObjectType* shiboType = reinterpret_cast(SbkType<"; s << type->name() << " >());" << endl; s << INDENT << "return "; bool isFirst = true; diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 39c18c3e..5c47a357 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -41,7 +41,7 @@ PyTypeObject SbkBaseType_Type = { PyObject_HEAD_INIT(0) /*ob_size*/ 0, /*tp_name*/ "Shiboken.ObjectType", - /*tp_basicsize*/ sizeof(SbkBaseType), + /*tp_basicsize*/ sizeof(SbkObjectType), /*tp_itemsize*/ 0, /*tp_dealloc*/ SbkBaseTypeDealloc, /*tp_print*/ 0, @@ -101,7 +101,7 @@ static PyGetSetDef SbkObjectGetSetList[] = { {0} // Sentinel }; -SbkBaseType SbkObject_Type = { { { +SbkObjectType SbkObject_Type = { { { PyObject_HEAD_INIT(&SbkBaseType_Type) /*ob_size*/ 0, /*tp_name*/ "Shiboken.Object", @@ -161,7 +161,7 @@ void SbkDeallocWrapper(PyObject* pyObj) // If I have ownership and is valid delete C++ pointer if (sbkObj->d->hasOwnership && sbkObj->d->validCppObject) { - SbkBaseType* sbkType = reinterpret_cast(pyObj->ob_type); + SbkObjectType* sbkType = reinterpret_cast(pyObj->ob_type); if (sbkType->d->is_multicpp) { Shiboken::DtorCallerVisitor visitor(sbkObj); Shiboken::walkThroughClassHierarchy(pyObj->ob_type, &visitor); @@ -185,7 +185,7 @@ void SbkDeallocWrapperWithPrivateDtor(PyObject* self) void SbkBaseTypeDealloc(PyObject* pyObj) { - SbkBaseType *sbkType = reinterpret_cast(pyObj->ob_type); + SbkObjectType* sbkType = reinterpret_cast(pyObj->ob_type); if (!sbkType->d) return; @@ -202,7 +202,7 @@ void SbkBaseTypeDealloc(PyObject* pyObj) PyObject* SbkBaseTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds) { // The meta type creates a new type when the Python programmer extends a wrapped C++ class. - SbkBaseType* newType = reinterpret_cast(PyType_Type.tp_new(metatype, args, kwds)); + SbkObjectType* newType = reinterpret_cast(PyType_Type.tp_new(metatype, args, kwds)); if (!newType) return 0; @@ -210,7 +210,7 @@ PyObject* SbkBaseTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwd SbkBaseTypePrivate* d = new SbkBaseTypePrivate; memset(d, 0, sizeof(SbkBaseTypePrivate)); - std::list bases = Shiboken::getCppBaseClasses(reinterpret_cast(newType)); + std::list bases = Shiboken::getCppBaseClasses(reinterpret_cast(newType)); if (bases.size() == 1) { SbkBaseTypePrivate* parentType = bases.front()->d; d->mi_offsets = parentType->mi_offsets; @@ -249,7 +249,7 @@ PyObject* SbkObjectTpNew(PyTypeObject* subtype, PyObject*, PyObject*) SbkObject* self = reinterpret_cast(subtype->tp_alloc(subtype, 0)); self->d = new SbkObjectPrivate; - SbkBaseType* sbkType = reinterpret_cast(subtype); + SbkObjectType* sbkType = reinterpret_cast(subtype); int numBases = ((sbkType->d && sbkType->d->is_multicpp) ? Shiboken::getNumberOfCppBaseClasses(subtype) : 1); self->d->cptr = new void*[numBases]; std::memset(self->d->cptr, 0, sizeof(void*)*numBases); @@ -282,7 +282,7 @@ void walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visi if (type->ob_type != &SbkBaseType_Type) { continue; } else { - SbkBaseType* sbkType = reinterpret_cast(type); + SbkObjectType* sbkType = reinterpret_cast(type); if (sbkType->d->is_user_type) walkThroughClassHierarchy(type, visitor); else @@ -311,7 +311,7 @@ bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr) // Wrapper metatype and base type ---------------------------------------------------------- -void DtorCallerVisitor::visit(SbkBaseType* node) +void DtorCallerVisitor::visit(SbkObjectType* node) { node->d->cpp_dtor(m_pyObj->d->cptr[m_count]); m_count++; @@ -385,7 +385,7 @@ class FindBaseTypeVisitor : public HierarchyVisitor { public: FindBaseTypeVisitor(PyTypeObject* typeToFind) : m_found(false), m_typeToFind(typeToFind) {} - virtual void visit(SbkBaseType* node) + virtual void visit(SbkObjectType* node) { if (reinterpret_cast(node) == m_typeToFind) { m_found = true; @@ -447,7 +447,7 @@ bool checkType(PyTypeObject* type) bool isUserType(PyTypeObject* type) { - return BaseType::checkType(type) && reinterpret_cast(type)->d->is_user_type; + return BaseType::checkType(type) && reinterpret_cast(type)->d->is_user_type; } bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType) @@ -461,101 +461,101 @@ bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType) return true; } -void* copy(SbkBaseType* self, const void* obj) +void* copy(SbkObjectType* self, const void* obj) { return self->d->obj_copier(obj); } -void setCopyFunction(SbkBaseType* self, ObjectCopierFunction func) +void setCopyFunction(SbkObjectType* self, ObjectCopierFunction func) { self->d->obj_copier = func; } -bool hasExternalCppConversions(SbkBaseType* self) +bool hasExternalCppConversions(SbkObjectType* self) { return self->d->ext_tocpp; } -void* callExternalCppConversion(SbkBaseType* self, PyObject* obj) +void* callExternalCppConversion(SbkObjectType* self, PyObject* obj) { return self->d->ext_tocpp(obj); } -void setExternalCppConversionFunction(SbkBaseType* self, ExtendedToCppFunc func) +void setExternalCppConversionFunction(SbkObjectType* self, ExtendedToCppFunc func) { self->d->ext_tocpp = func; } -void setExternalIsConvertibleFunction(SbkBaseType* self, ExtendedIsConvertibleFunc func) +void setExternalIsConvertibleFunction(SbkObjectType* self, ExtendedIsConvertibleFunc func) { self->d->ext_isconvertible = func; } -bool isExternalConvertible(SbkBaseType* self, PyObject* obj) +bool isExternalConvertible(SbkObjectType* self, PyObject* obj) { return self->d->ext_isconvertible && self->d->ext_isconvertible(obj); } -bool hasCast(SbkBaseType* self) +bool hasCast(SbkObjectType* self) { return self->d->mi_specialcast; } -void* cast(SbkBaseType* self, SbkObject* obj, PyTypeObject *target) +void* cast(SbkObjectType* self, SbkObject* obj, PyTypeObject *target) { - return self->d->mi_specialcast(Wrapper::cppPointer(obj, target), reinterpret_cast(target)); + return self->d->mi_specialcast(Wrapper::cppPointer(obj, target), reinterpret_cast(target)); } -void setCastFunction(SbkBaseType* self, SpecialCastFunction func) +void setCastFunction(SbkObjectType* self, SpecialCastFunction func) { self->d->mi_specialcast = func; } -void setOriginalName(SbkBaseType* self, const char* name) +void setOriginalName(SbkObjectType* self, const char* name) { if (self->d->original_name) free(self->d->original_name); self->d->original_name = strdup(name); } -const char* getOriginalName(SbkBaseType* self) +const char* getOriginalName(SbkObjectType* self) { return self->d->original_name; } -void setTypeDiscoveryFunction(SbkBaseType* self, TypeDiscoveryFunc func) +void setTypeDiscoveryFunction(SbkObjectType* self, TypeDiscoveryFunc func) { self->d->type_discovery = func; } -TypeDiscoveryFunc getTypeDiscoveryFunction(SbkBaseType* self) +TypeDiscoveryFunc getTypeDiscoveryFunction(SbkObjectType* self) { return self->d->type_discovery; } -void copyMultimpleheritance(SbkBaseType* self, SbkBaseType* other) +void copyMultimpleheritance(SbkObjectType* self, SbkObjectType* other) { self->d->mi_init = other->d->mi_init; self->d->mi_offsets = other->d->mi_offsets; self->d->mi_specialcast = other->d->mi_specialcast; } -void setMultipleIheritanceFunction(SbkBaseType* self, MultipleInheritanceInitFunction function) +void setMultipleIheritanceFunction(SbkObjectType* self, MultipleInheritanceInitFunction function) { self->d->mi_init = function; } -MultipleInheritanceInitFunction getMultipleIheritanceFunction(SbkBaseType* self) +MultipleInheritanceInitFunction getMultipleIheritanceFunction(SbkObjectType* self) { return self->d->mi_init; } -void setDestructorFunction(SbkBaseType* self, ObjectDestructor func) +void setDestructorFunction(SbkObjectType* self, ObjectDestructor func) { self->d->cpp_dtor = func; } -void initPrivateData(SbkBaseType* self) +void initPrivateData(SbkObjectType* self) { self->d = new SbkBaseTypePrivate; memset(self->d, 0, sizeof(SbkBaseTypePrivate)); @@ -740,7 +740,7 @@ void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType) { PyTypeObject* type = pyObj->ob_type; int idx = 0; - if (reinterpret_cast(type)->d->is_multicpp) + if (reinterpret_cast(type)->d->is_multicpp) idx = getTypeIndexOnHierarchy(type, desiredType); return pyObj->d->cptr[idx]; } @@ -748,7 +748,7 @@ void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType) bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr) { int idx = 0; - if (reinterpret_cast(sbkObj->ob_type)->d->is_multicpp) + if (reinterpret_cast(sbkObj->ob_type)->d->is_multicpp) idx = getTypeIndexOnHierarchy(sbkObj->ob_type, desiredType); bool alreadyInitialized = sbkObj->d->cptr[idx]; @@ -771,7 +771,7 @@ bool isValid(PyObject* pyObj) return false; } -PyObject* newObject(SbkBaseType* instanceType, +PyObject* newObject(SbkObjectType* instanceType, void* cptr, bool hasOwnership, bool isExactType, @@ -783,7 +783,7 @@ PyObject* newObject(SbkBaseType* instanceType, if (typeName) { tr = TypeResolver::get(typeName); if (tr) - instanceType = reinterpret_cast(tr->pythonType()); + instanceType = reinterpret_cast(tr->pythonType()); } if (!tr) instanceType = BindingManager::instance().resolveType(cptr, instanceType); @@ -951,7 +951,7 @@ void deallocData(SbkObject* self) void setTypeUserData(SbkObject* wrapper, void *user_data, DeleteUserDataFunc d_func) { - SbkBaseType* ob_type = reinterpret_cast(wrapper->ob_type); + SbkObjectType* ob_type = reinterpret_cast(wrapper->ob_type); if (ob_type->d->user_data) ob_type->d->d_func(ob_type->d->user_data); @@ -961,7 +961,7 @@ void setTypeUserData(SbkObject* wrapper, void *user_data, DeleteUserDataFunc d_f void* getTypeUserData(SbkObject* wrapper) { - return reinterpret_cast(wrapper->ob_type)->d->user_data; + return reinterpret_cast(wrapper->ob_type)->d->user_data; } void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append) diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index aa1301df..80207e25 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -51,7 +51,7 @@ struct LIBSHIBOKEN_API SbkObject LIBSHIBOKEN_API void SbkDeallocWrapper(PyObject* pyObj); LIBSHIBOKEN_API void SbkDeallocWrapperWithPrivateDtor(PyObject* self); -struct SbkBaseType; +struct SbkObjectType; /// Function signature for the multiple inheritance information initializers that should be provided by classes with multiple inheritance. typedef int* (*MultipleInheritanceInitFunction)(const void*); @@ -61,9 +61,9 @@ typedef int* (*MultipleInheritanceInitFunction)(const void*); * part of a multiple inheritance hierarchy. * The implementation of this function is auto generated by the generator and you don't need to care about it. */ -typedef void* (*SpecialCastFunction)(void*, SbkBaseType*); +typedef void* (*SpecialCastFunction)(void*, SbkObjectType*); typedef void* (*ObjectCopierFunction)(const void*); -typedef SbkBaseType* (*TypeDiscoveryFunc)(void*, SbkBaseType*); +typedef SbkObjectType* (*TypeDiscoveryFunc)(void*, SbkObjectType*); typedef void* (*ExtendedToCppFunc)(PyObject*); typedef bool (*ExtendedIsConvertibleFunc)(PyObject*); @@ -74,12 +74,12 @@ typedef void (*DeleteUserDataFunc)(void*); typedef void (*ObjectDestructor)(void*); extern LIBSHIBOKEN_API PyTypeObject SbkBaseType_Type; -extern LIBSHIBOKEN_API SbkBaseType SbkObject_Type; +extern LIBSHIBOKEN_API SbkObjectType SbkObject_Type; struct SbkBaseTypePrivate; /// PyTypeObject extended with C++ multiple inheritance information. -struct LIBSHIBOKEN_API SbkBaseType +struct LIBSHIBOKEN_API SbkObjectType { PyHeapTypeObject super; SbkBaseTypePrivate* d; @@ -129,32 +129,32 @@ LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject* myType, PyTypeObjec /** * Call copy function for the object type **/ -LIBSHIBOKEN_API void* copy(SbkBaseType* self, const void *obj); -LIBSHIBOKEN_API void setCopyFunction(SbkBaseType* self, ObjectCopierFunction func); +LIBSHIBOKEN_API void* copy(SbkObjectType* self, const void *obj); +LIBSHIBOKEN_API void setCopyFunction(SbkObjectType* self, ObjectCopierFunction func); -LIBSHIBOKEN_API void setExternalCppConversionFunction(SbkBaseType* self, ExtendedToCppFunc func); -LIBSHIBOKEN_API void setExternalIsConvertibleFunction(SbkBaseType* self, ExtendedIsConvertibleFunc func); -LIBSHIBOKEN_API bool hasExternalCppConversions(SbkBaseType* self); -LIBSHIBOKEN_API bool isExternalConvertible(SbkBaseType* self, PyObject* obj); -LIBSHIBOKEN_API void* callExternalCppConversion(SbkBaseType* self, PyObject* obj); +LIBSHIBOKEN_API void setExternalCppConversionFunction(SbkObjectType* self, ExtendedToCppFunc func); +LIBSHIBOKEN_API void setExternalIsConvertibleFunction(SbkObjectType* self, ExtendedIsConvertibleFunc func); +LIBSHIBOKEN_API bool hasExternalCppConversions(SbkObjectType* self); +LIBSHIBOKEN_API bool isExternalConvertible(SbkObjectType* self, PyObject* obj); +LIBSHIBOKEN_API void* callExternalCppConversion(SbkObjectType* self, PyObject* obj); -LIBSHIBOKEN_API bool hasCast(SbkBaseType* self); -LIBSHIBOKEN_API void* cast(SbkBaseType* self, SbkObject* obj, PyTypeObject* target); -LIBSHIBOKEN_API void setCastFunction(SbkBaseType* self, SpecialCastFunction func); +LIBSHIBOKEN_API bool hasCast(SbkObjectType* self); +LIBSHIBOKEN_API void* cast(SbkObjectType* self, SbkObject* obj, PyTypeObject* target); +LIBSHIBOKEN_API void setCastFunction(SbkObjectType* self, SpecialCastFunction func); -LIBSHIBOKEN_API void setOriginalName(SbkBaseType* self, const char* name); -LIBSHIBOKEN_API const char* getOriginalName(SbkBaseType* self); +LIBSHIBOKEN_API void setOriginalName(SbkObjectType* self, const char* name); +LIBSHIBOKEN_API const char* getOriginalName(SbkObjectType* self); -LIBSHIBOKEN_API void setTypeDiscoveryFunction(SbkBaseType* self, TypeDiscoveryFunc func); -LIBSHIBOKEN_API TypeDiscoveryFunc getTypeDiscoveryFunction(SbkBaseType* self); +LIBSHIBOKEN_API void setTypeDiscoveryFunction(SbkObjectType* self, TypeDiscoveryFunc func); +LIBSHIBOKEN_API TypeDiscoveryFunc getTypeDiscoveryFunction(SbkObjectType* self); -LIBSHIBOKEN_API void copyMultimpleheritance(SbkBaseType* self, SbkBaseType* other); -LIBSHIBOKEN_API void setMultipleIheritanceFunction(SbkBaseType* self, MultipleInheritanceInitFunction func); -LIBSHIBOKEN_API MultipleInheritanceInitFunction getMultipleIheritanceFunction(SbkBaseType* self); +LIBSHIBOKEN_API void copyMultimpleheritance(SbkObjectType* self, SbkObjectType* other); +LIBSHIBOKEN_API void setMultipleIheritanceFunction(SbkObjectType* self, MultipleInheritanceInitFunction func); +LIBSHIBOKEN_API MultipleInheritanceInitFunction getMultipleIheritanceFunction(SbkObjectType* self); -LIBSHIBOKEN_API void setDestructorFunction(SbkBaseType* self, ObjectDestructor func); +LIBSHIBOKEN_API void setDestructorFunction(SbkObjectType* self, ObjectDestructor func); -LIBSHIBOKEN_API void initPrivateData(SbkBaseType* self); +LIBSHIBOKEN_API void initPrivateData(SbkObjectType* self); } namespace Wrapper { @@ -166,7 +166,7 @@ LIBSHIBOKEN_API bool checkType(PyObject* pyObj); LIBSHIBOKEN_API bool isUserType(PyObject* pyObj); -LIBSHIBOKEN_API PyObject* newObject(SbkBaseType* instanceType, +LIBSHIBOKEN_API PyObject* newObject(SbkObjectType* instanceType, void* cptr, bool hasOwnership = true, bool isExactType = false, diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h index 702fdbd0..ebf50d44 100644 --- a/libshiboken/basewrapper_p.h +++ b/libshiboken/basewrapper_p.h @@ -28,7 +28,7 @@ #include struct SbkObject; -struct SbkBaseType; +struct SbkObjectType; namespace Shiboken { @@ -125,7 +125,7 @@ class HierarchyVisitor public: HierarchyVisitor() : m_wasFinished(false) {} virtual ~HierarchyVisitor() {} - virtual void visit(SbkBaseType* node) = 0; + virtual void visit(SbkObjectType* node) = 0; void finish() { m_wasFinished = true; }; bool wasFinished() const { return m_wasFinished; } private: @@ -137,7 +137,7 @@ class BaseCountVisitor : public HierarchyVisitor public: BaseCountVisitor() : m_count(0) {} - void visit(SbkBaseType*) + void visit(SbkObjectType*) { m_count++; } @@ -152,21 +152,21 @@ class BaseAccumulatorVisitor : public HierarchyVisitor public: BaseAccumulatorVisitor() {} - void visit(SbkBaseType* node) + void visit(SbkObjectType* node) { m_bases.push_back(node); } - std::list bases() const { return m_bases; } + std::list bases() const { return m_bases; } private: - std::list m_bases; + std::list m_bases; }; class GetIndexVisitor : public HierarchyVisitor { public: GetIndexVisitor(PyTypeObject* desiredType) : m_index(-1), m_desiredType(desiredType) {} - virtual void visit(SbkBaseType* node) + virtual void visit(SbkObjectType* node) { m_index++; if (PyType_IsSubtype(reinterpret_cast(node), m_desiredType)) @@ -183,7 +183,7 @@ class DtorCallerVisitor : public HierarchyVisitor { public: DtorCallerVisitor(SbkObject* pyObj) : m_count(0), m_pyObj(pyObj) {} - void visit(SbkBaseType* node); + void visit(SbkObjectType* node); private: int m_count; SbkObject* m_pyObj; @@ -211,7 +211,7 @@ inline int getNumberOfCppBaseClasses(PyTypeObject* baseType) return visitor.count(); } -inline std::list getCppBaseClasses(PyTypeObject* baseType) +inline std::list getCppBaseClasses(PyTypeObject* baseType) { BaseAccumulatorVisitor visitor; walkThroughClassHierarchy(baseType, &visitor); diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index 3742f6fe..dd9fb5d1 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -37,8 +37,8 @@ typedef google::dense_hash_map WrapperMap; class Graph { public: - typedef std::list NodeList; - typedef google::dense_hash_map Edges; + typedef std::list NodeList; + typedef google::dense_hash_map Edges; Edges m_edges; @@ -47,7 +47,7 @@ class Graph m_edges.set_empty_key(0); } - void addEdge(SbkBaseType* from, SbkBaseType* to) + void addEdge(SbkObjectType* from, SbkObjectType* to) { m_edges[from].push_back(to); } @@ -61,7 +61,7 @@ class Graph Edges::const_iterator i = m_edges.begin(); for (; i != m_edges.end(); ++i) { - SbkBaseType* node1 = i->first; + SbkObjectType* node1 = i->first; const NodeList& nodeList = i->second; NodeList::const_iterator j = nodeList.begin(); for (; j != nodeList.end(); ++j) @@ -71,14 +71,14 @@ class Graph } #endif - SbkBaseType* identifyType(void* cptr, SbkBaseType* type, SbkBaseType* baseType) const + SbkObjectType* identifyType(void* cptr, SbkObjectType* type, SbkObjectType* baseType) const { Edges::const_iterator edgesIt = m_edges.find(type); if (edgesIt != m_edges.end()) { const NodeList& adjNodes = m_edges.find(type)->second; NodeList::const_iterator i = adjNodes.begin(); for (; i != adjNodes.end(); ++i) { - SbkBaseType* newType = identifyType(cptr, *i, baseType); + SbkObjectType* newType = identifyType(cptr, *i, baseType); if (newType) return newType; } @@ -166,7 +166,7 @@ bool BindingManager::hasWrapper(const void* cptr) void BindingManager::registerWrapper(SbkObject* pyObj, void* cptr) { - SbkBaseType* instanceType = reinterpret_cast(pyObj->ob_type); + SbkObjectType* instanceType = reinterpret_cast(pyObj->ob_type); SbkBaseTypePrivate* d = instanceType->d; if (!d) @@ -187,7 +187,7 @@ void BindingManager::registerWrapper(SbkObject* pyObj, void* cptr) void BindingManager::releaseWrapper(SbkObject* sbkObj) { - SbkBaseType* sbkType = reinterpret_cast(sbkObj->ob_type); + SbkObjectType* sbkType = reinterpret_cast(sbkObj->ob_type); SbkBaseTypePrivate* d = sbkType->d; int numBases = ((d && d->is_multicpp) ? getNumberOfCppBaseClasses(sbkObj->ob_type) : 1); @@ -255,14 +255,14 @@ PyObject* BindingManager::getOverride(const void* cptr, const char* methodName) return 0; } -void BindingManager::addClassInheritance(SbkBaseType* parent, SbkBaseType* child) +void BindingManager::addClassInheritance(SbkObjectType* parent, SbkObjectType* child) { m_d->classHierarchy.addEdge(parent, child); } -SbkBaseType* BindingManager::resolveType(void* cptr, SbkBaseType* type) +SbkObjectType* BindingManager::resolveType(void* cptr, SbkObjectType* type) { - SbkBaseType* identifiedType = m_d->classHierarchy.identifyType(cptr, type, type); + SbkObjectType* identifiedType = m_d->classHierarchy.identifyType(cptr, type, type); return identifiedType ? identifiedType : type; } diff --git a/libshiboken/bindingmanager.h b/libshiboken/bindingmanager.h index 2ead2351..b6d4ac42 100644 --- a/libshiboken/bindingmanager.h +++ b/libshiboken/bindingmanager.h @@ -28,7 +28,7 @@ #include "shibokenmacros.h" struct SbkObject; -struct SbkBaseType; +struct SbkObjectType; namespace Shiboken { @@ -46,8 +46,8 @@ class LIBSHIBOKEN_API BindingManager SbkObject* retrieveWrapper(const void* cptr); PyObject* getOverride(const void* cptr, const char* methodName); - void addClassInheritance(SbkBaseType* parent, SbkBaseType* child); - SbkBaseType* resolveType(void* cptr, SbkBaseType* type); + void addClassInheritance(SbkObjectType* parent, SbkObjectType* child); + SbkObjectType* resolveType(void* cptr, SbkObjectType* type); std::set getAllPyObjects(); private: diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index d6a3dd5e..afc4989f 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -99,7 +99,7 @@ struct CppObjectCopier { static inline T* copy(const T& obj) { - return reinterpret_cast(BaseType::copy(reinterpret_cast(SbkType()), &obj)); + return reinterpret_cast(BaseType::copy(reinterpret_cast(SbkType()), &obj)); } }; @@ -113,7 +113,7 @@ inline PyObject* createWrapper(const T* cppobj, bool hasOwnership = false, bool const char* typeName = 0; if (!isExactType) typeName = typeid(*const_cast(cppobj)).name(); - return Wrapper::newObject(reinterpret_cast(SbkType()), + return Wrapper::newObject(reinterpret_cast(SbkType()), const_cast(cppobj), hasOwnership, isExactType, typeName); } @@ -213,7 +213,7 @@ struct ValueTypeConverter { if (PyObject_TypeCheck(pyobj, SbkType())) return true; - SbkBaseType* shiboType = reinterpret_cast(SbkType()); + SbkObjectType* shiboType = reinterpret_cast(SbkType()); return BaseType::isExternalConvertible(shiboType, pyobj); } static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } @@ -231,7 +231,7 @@ struct ValueTypeConverter static inline T toCpp(PyObject* pyobj) { if (!PyObject_TypeCheck(pyobj, SbkType())) { - SbkBaseType* shiboType = reinterpret_cast(SbkType()); + SbkObjectType* shiboType = reinterpret_cast(SbkType()); if (BaseType::hasExternalCppConversions(shiboType) && isConvertible(pyobj)) { T* cptr = reinterpret_cast(BaseType::callExternalCppConversion(shiboType, pyobj)); std::auto_ptr cptr_auto_ptr(cptr); @@ -271,7 +271,7 @@ struct ObjectTypeConverter { if (pyobj == Py_None) return 0; - SbkBaseType* shiboType = reinterpret_cast(pyobj->ob_type); + SbkObjectType* shiboType = reinterpret_cast(pyobj->ob_type); if (BaseType::hasCast(shiboType)) return reinterpret_cast(BaseType::cast(shiboType, reinterpret_cast(pyobj), SbkType())); return (T*) Wrapper::cppPointer(reinterpret_cast(pyobj), SbkType()); From b2096155a231797afd397acc8908acb691f3c732 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Fri, 19 Nov 2010 14:30:22 -0300 Subject: [PATCH 134/564] Created private pointer for Shiboken Meta Type. Renamed ObjectType to BaseType. Reviewer: Luciano Wolf Hugo Parente Lima --- generator/cppgenerator.cpp | 128 +++++------ generator/headergenerator.cpp | 6 +- libshiboken/basewrapper.cpp | 396 ++++++++++++++++++++++----------- libshiboken/basewrapper.h | 193 ++++++++-------- libshiboken/basewrapper_p.h | 50 ++++- libshiboken/bindingmanager.cpp | 43 ++-- libshiboken/bindingmanager.h | 6 +- libshiboken/conversions.h | 30 ++- libshiboken/typeresolver.h | 2 - 9 files changed, 515 insertions(+), 339 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 239bd753..537c658f 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -788,13 +788,13 @@ void CppGenerator::writeMetaObjectMethod(QTextStream& s, const AbstractMetaClass { Indentation indentation(INDENT); s << INDENT << "SbkObject* pySelf = BindingManager::instance().retrieveWrapper(this);\n" - << INDENT << "void* typeData = Shiboken::getTypeUserData(pySelf);" << endl + << INDENT << "void* typeData = Shiboken::Wrapper::getTypeUserData(pySelf);" << endl << INDENT << "if (!typeData) {" << endl; { Indentation indentation2(INDENT); s << INDENT << "m_metaObject = PySide::DynamicQMetaObject::createBasedOn((PyObject*)pySelf, pySelf->ob_type, &" << metaClass->qualifiedCppName() << "::staticMetaObject);" << endl - << INDENT << "Shiboken::setTypeUserData(pySelf, m_metaObject, &Shiboken::callCppDestructor);" << endl; + << INDENT << "Shiboken::Wrapper::setTypeUserData(pySelf, m_metaObject, PySide::deleteDynamicQMetaObject);" << endl; } s << INDENT << "} else {" << endl; { @@ -830,7 +830,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun // Check if the right constructor was called. if (!metaClass->hasPrivateDestructor()) { - s << INDENT << "if (Shiboken::isUserType(self) && !Shiboken::canCallConstructor(self->ob_type, Shiboken::SbkType<" << metaClass->qualifiedCppName() << " >()))" << endl; + s << INDENT << "if (Shiboken::Wrapper::isUserType(self) && !Shiboken::BaseType::canCallConstructor(self->ob_type, Shiboken::SbkType<" << metaClass->qualifiedCppName() << " >()))" << endl; Indentation indent(INDENT); s << INDENT << "return " << m_currentErrorCode << ';' << endl << endl; } @@ -866,8 +866,8 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun s << INDENT << "SbkObject* sbkSelf = reinterpret_cast(self);" << endl; if (metaClass->isAbstract() || metaClass->baseClassNames().size() > 1) { - s << INDENT << "SbkObjectType* type = reinterpret_cast(self->ob_type);" << endl; - s << INDENT << "SbkObjectType* myType = reinterpret_cast(" << cpythonTypeNameExt(metaClass->typeEntry()) << ");" << endl; + s << INDENT << "SbkBaseType* type = reinterpret_cast(self->ob_type);" << endl; + s << INDENT << "SbkBaseType* myType = reinterpret_cast(" << cpythonTypeNameExt(metaClass->typeEntry()) << ");" << endl; } if (metaClass->isAbstract()) { @@ -891,9 +891,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun } { Indentation indentation(INDENT); - s << INDENT << "type->mi_init = myType->mi_init;" << endl; - s << INDENT << "type->mi_offsets = myType->mi_offsets;" << endl; - s << INDENT << "type->mi_specialcast = myType->mi_specialcast;" << endl; + s << INDENT << "Shiboken::BaseType::copyMultimpleheritance(type, myType);" << endl; } if (!metaClass->isAbstract()) s << INDENT << '}' << endl << endl; @@ -1175,7 +1173,7 @@ void CppGenerator::writeMethodWrapper(QTextStream& s, const AbstractMetaFunction s << INDENT << "if (!isReverse" << endl; { Indentation indent(INDENT); - s << INDENT << "&& Shiboken::isShibokenType(arg)" << endl; + s << INDENT << "&& Shiboken::Wrapper::checkType(arg)" << endl; s << INDENT << "&& !PyObject_TypeCheck(arg, self->ob_type)" << endl; s << INDENT << "&& PyObject_HasAttrString(arg, const_cast(\"" << revOpName << "\"))) {" << endl; // This PyObject_CallMethod call will emit lots of warnings like @@ -2046,7 +2044,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f virtualCall = virtualCall.replace("%CLASS_NAME", func->ownerClass()->qualifiedCppName()); normalCall = normalCall.replace("::%CLASS_NAME::", ""); methodCall = ""; - mc << "(Shiboken::isUserType(self) ? " << virtualCall << ":" << normalCall << ")"; + mc << "(Shiboken::Wrapper::isUserType(self) ? " << virtualCall << ":" << normalCall << ")"; } } } @@ -2154,7 +2152,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f break; } - s << INDENT << "Shiboken::keepReference(reinterpret_cast(self), \""; + s << INDENT << "Shiboken::Wrapper::keepReference(reinterpret_cast(self), \""; QString varName = arg_mod.referenceCounts.first().varName; if (varName.isEmpty()) varName = func->minimalSignature() + QString().number(arg_mod.index); @@ -2226,12 +2224,12 @@ void CppGenerator::writeMultipleInheritanceInitializerFunction(QTextStream& s, c void CppGenerator::writeSpecialCastFunction(QTextStream& s, const AbstractMetaClass* metaClass) { QString className = metaClass->qualifiedCppName(); - s << "static void* " << cpythonSpecialCastFunctionName(metaClass) << "(void* obj, SbkObjectType* desiredType)\n"; + s << "static void* " << cpythonSpecialCastFunctionName(metaClass) << "(void* obj, SbkBaseType* desiredType)\n"; s << "{\n"; s << INDENT << className << "* me = reinterpret_cast<" << className << "*>(obj);\n"; bool firstClass = true; foreach (const AbstractMetaClass* baseClass, getAllAncestors(metaClass)) { - s << INDENT << (!firstClass ? "else " : "") << "if (desiredType == reinterpret_cast(" << cpythonTypeNameExt(baseClass->typeEntry()) << "))\n"; + s << INDENT << (!firstClass ? "else " : "") << "if (desiredType == reinterpret_cast(" << cpythonTypeNameExt(baseClass->typeEntry()) << "))\n"; Indentation indent(INDENT); s << INDENT << "return static_cast<" << baseClass->qualifiedCppName() << "*>(me);\n"; firstClass = false; @@ -2283,11 +2281,11 @@ void CppGenerator::writeExtendedToCppFunction(QTextStream& s, const TypeEntry* e void CppGenerator::writeExtendedConverterInitialization(QTextStream& s, const TypeEntry* externalType, const QList& conversions) { s << INDENT << "// Extended implicit conversions for " << externalType->targetLangPackage() << '.' << externalType->name() << endl; - s << INDENT << "shiboType = reinterpret_cast("; + s << INDENT << "shiboType = reinterpret_cast("; s << cppApiVariableName(externalType->targetLangPackage()) << '['; s << getTypeIndexVariableName(externalType) << "]);" << endl; - s << INDENT << "shiboType->ext_isconvertible = " << extendedIsConvertibleFunctionName(externalType) << ';' << endl; - s << INDENT << "shiboType->ext_tocpp = " << extendedToCppFunctionName(externalType) << ';' << endl; + s << INDENT << "Shiboken::BaseType::setExternalIsConvertibleFunction(shiboType, " << extendedIsConvertibleFunctionName(externalType) << ");" << endl; + s << INDENT << "Shiboken::BaseType::setExternalCppConversionFunction(shiboType, " << extendedToCppFunctionName(externalType) << ");" << endl; } QString CppGenerator::multipleInheritanceInitializerFunctionName(const AbstractMetaClass* metaClass) @@ -2326,13 +2324,9 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* QString tp_init; QString tp_new; QString tp_dealloc; - QString cpp_dtor('0'); QString tp_as_number('0'); QString tp_as_sequence('0'); QString tp_hash('0'); - QString mi_init('0'); - QString obj_copier('0'); - QString mi_specialcast('0'); QString cppClassName = metaClass->qualifiedCppName(); QString className = cpythonTypeName(metaClass).replace(QRegExp("_Type$"), ""); QString baseClassName('0'); @@ -2369,14 +2363,6 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* else deallocClassName = cppClassName; tp_dealloc = "&SbkDeallocWrapper"; - - QString dtorClassName = metaClass->qualifiedCppName(); -#ifdef AVOID_PROTECTED_HACK - if (metaClass->hasProtectedDestructor()) - dtorClassName = wrapperName(metaClass); -#endif - cpp_dtor = "&Shiboken::callCppDestructor<" + dtorClassName + " >"; - tp_init = onlyPrivCtor ? "0" : cpythonFunctionName(ctors.first()); } @@ -2417,25 +2403,19 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* // class or some ancestor has multiple inheritance const AbstractMetaClass* miClass = getMultipleInheritingClass(metaClass); if (miClass) { - if (metaClass == miClass) { - mi_init = multipleInheritanceInitializerFunctionName(miClass); + if (metaClass == miClass) writeMultipleInheritanceInitializerFunction(s, metaClass); - } - mi_specialcast = '&'+cpythonSpecialCastFunctionName(metaClass); writeSpecialCastFunction(s, metaClass); s << endl; } - if (metaClass->typeEntry()->isValue() && shouldGenerateCppWrapper(metaClass)) - obj_copier = '&' + cpythonBaseName(metaClass) + "_ObjCopierFunc"; - if (!metaClass->typeEntry()->hashFunction().isEmpty()) tp_hash = '&' + cpythonBaseName(metaClass) + "_HashFunc"; s << "// Class Definition -----------------------------------------------" << endl; s << "extern \"C\" {" << endl; - s << "static SbkObjectType " << className + "_Type" << " = { { {" << endl; - s << INDENT << "PyObject_HEAD_INIT(&SbkObjectType_Type)" << endl; + s << "static SbkBaseType " << className + "_Type" << " = { { {" << endl; + s << INDENT << "PyObject_HEAD_INIT(&SbkBaseType_Type)" << endl; s << INDENT << "/*ob_size*/ 0," << endl; s << INDENT << "/*tp_name*/ \"" << metaClass->fullName() << "\"," << endl; s << INDENT << "/*tp_basicsize*/ sizeof(SbkObject)," << endl; @@ -2482,22 +2462,11 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* s << INDENT << "/*tp_subclasses*/ 0," << endl; s << INDENT << "/*tp_weaklist*/ 0" << endl; s << "}, }," << endl; - s << INDENT << "/*mi_offsets*/ 0," << endl; - s << INDENT << "/*mi_init*/ " << mi_init << ',' << endl; - s << INDENT << "/*mi_specialcast*/ " << mi_specialcast << ',' << endl; - s << INDENT << "/*type_discovery*/ 0," << endl; - s << INDENT << "/*obj_copier*/ " << obj_copier << ',' << endl; - s << INDENT << "/*ext_isconvertible*/ 0," << endl; - s << INDENT << "/*ext_tocpp*/ 0," << endl; - s << INDENT << "/*cpp_dtor*/ " << cpp_dtor << ',' << endl; - s << INDENT << "/*is_multicpp*/ 0," << endl; - s << INDENT << "/*is_user_type*/ 0," << endl; + s << INDENT << "/*priv_data*/ 0" << endl; + s << "};" << endl; QString suffix; if (metaClass->typeEntry()->isObject() || metaClass->typeEntry()->isQObject()) suffix = "*"; - s << INDENT << "/*original_name*/ \"" << metaClass->qualifiedCppName() << suffix << "\"," << endl; - s << INDENT << "/*user_data*/ 0" << endl; - s << "};" << endl; s << "} //extern" << endl; } @@ -2757,7 +2726,7 @@ void CppGenerator::writeSetterFunction(QTextStream& s, const AbstractMetaField* bool pythonWrapperRefCounting = metaField->type()->typeEntry()->isObject() || metaField->type()->isValuePointer(); if (pythonWrapperRefCounting) { - s << INDENT << "Shiboken::keepReference(reinterpret_cast(self), \""; + s << INDENT << "Shiboken::Wrapper::keepReference(reinterpret_cast(self), \""; s << metaField->name() << "\", value);" << endl; //s << INDENT << "Py_XDECREF(oldvalue);" << endl; s << endl; @@ -3232,6 +3201,9 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m s << '{' << endl; s << INDENT << cpythonTypeNameExt(metaClass->typeEntry()) << " = reinterpret_cast(&" << cpythonTypeName(metaClass->typeEntry()) << ");" << endl << endl; + // alloc private data + s << INDENT << "Shiboken::BaseType::initPrivateData(&" << cpythonTypeName(metaClass->typeEntry()) << ");" << endl; + // class inject-code target/beginning if (!metaClass->typeEntry()->codeSnips().isEmpty()) { writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), CodeSnip::Beginning, TypeSystem::TargetLangCode, 0, 0, metaClass); @@ -3240,6 +3212,7 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m if (metaClass->baseClass()) s << INDENT << pyTypeName << ".super.ht_type.tp_base = " << cpythonTypeNameExt(metaClass->baseClass()->typeEntry()) << ';' << endl; + // Multiple inheritance const AbstractMetaClassList baseClasses = getBaseClasses(metaClass); if (metaClass->baseClassNames().size() > 1) { @@ -3253,28 +3226,55 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m s << INDENT << bases.join(", ") << ");" << endl << endl; } - // Fill multiple inheritance init function, if needed. + // Fill multiple inheritance data, if needed. const AbstractMetaClass* miClass = getMultipleInheritingClass(metaClass); - if (miClass && miClass != metaClass) { - s << INDENT << cpythonTypeName(metaClass) << ".mi_init = "; - s << "reinterpret_cast(" + cpythonTypeNameExt(miClass->typeEntry()) + ")->mi_init;" << endl << endl; + if (miClass) { + s << INDENT << "MultipleInheritanceInitFunction func;" << endl; + + if (miClass == metaClass) + s << INDENT << "func = " << multipleInheritanceInitializerFunctionName(miClass) << ";" << endl; + else + s << INDENT << "func = Shiboken::BaseType::getMultipleIheritanceFunction(reinterpret_cast(" << cpythonTypeNameExt(miClass->typeEntry()) << "));" << endl; + + s << INDENT << "Shiboken::BaseType::setMultipleIheritanceFunction(&" << cpythonTypeName(metaClass) << ", func);" << endl; + s << INDENT << "Shiboken::BaseType::setCastFunction(&" << cpythonTypeName(metaClass) << ", &" << cpythonSpecialCastFunctionName(metaClass) << ");" << endl; } + // Fill destrutor + QString dtorClassName = metaClass->qualifiedCppName(); + if (!metaClass->isNamespace() && !metaClass->hasPrivateDestructor()) { +#ifdef AVOID_PROTECTED_HACK + if (metaClass->hasProtectedDestructor()) + dtorClassName = wrapperName(metaClass); +#endif + s << INDENT << "Shiboken::BaseType::setDestructorFunction(&" << cpythonTypeName(metaClass) << ", &Shiboken::callCppDestructor<" << dtorClassName << " >);" << endl; + } + + // Fill copy function + if (metaClass->typeEntry()->isValue() && shouldGenerateCppWrapper(metaClass)) + s << INDENT << "Shiboken::BaseType::setCopyFunction(&" << cpythonTypeName(metaClass) << ", &" << cpythonBaseName(metaClass) + "_ObjCopierFunc);" << endl; + + s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << pyTypeName << ") < 0)" << endl; + s << INDENT << INDENT << "return;" << endl << endl; + // Set typediscovery struct or fill the struct of another one if (metaClass->isPolymorphic()) { s << INDENT << "// Fill type discovery information" << endl; if (metaClass->baseClass()) { - s << INDENT << cpythonTypeName(metaClass) << ".type_discovery = &" << cpythonBaseName(metaClass) << "_typeDiscovery;" << endl; + s << INDENT << "Shiboken::BaseType::setTypeDiscoveryFunction(&" << cpythonTypeName(metaClass) << ", &" << cpythonBaseName(metaClass) << "_typeDiscovery);" << endl; s << INDENT << "Shiboken::BindingManager& bm = Shiboken::BindingManager::instance();" << endl; foreach (const AbstractMetaClass* base, baseClasses) { - s << INDENT << "bm.addClassInheritance(reinterpret_cast(" << cpythonTypeNameExt(base->typeEntry()) << "), &" << cpythonTypeName(metaClass) << ");" << endl; + s << INDENT << "bm.addClassInheritance(reinterpret_cast(" << cpythonTypeNameExt(base->typeEntry()) << "), &" << cpythonTypeName(metaClass) << ");" << endl; } } s << endl; } - s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << pyTypeName << ") < 0)" << endl; - s << INDENT << INDENT << "return;" << endl << endl; + // Set OriginalName + QByteArray suffix; + if (metaClass->typeEntry()->isObject() || metaClass->typeEntry()->isQObject()) + suffix = "*"; + s << INDENT << "Shiboken::BaseType::setOriginalName(&" << pyTypeName << ", \"" << metaClass->qualifiedCppName() << suffix << "\");" << endl; if (metaClass->enclosingClass() && (metaClass->enclosingClass()->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass) ) { s << INDENT << "PyDict_SetItemString(module," @@ -3345,7 +3345,7 @@ void CppGenerator::writeTypeDiscoveryFunction(QTextStream& s, const AbstractMeta { QString polymorphicExpr = metaClass->typeEntry()->polymorphicIdValue(); - s << "static SbkObjectType* " << cpythonBaseName(metaClass) << "_typeDiscovery(void* cptr, SbkObjectType* instanceType)\n{" << endl; + s << "static SbkBaseType* " << cpythonBaseName(metaClass) << "_typeDiscovery(void* cptr, SbkBaseType* instanceType)\n{" << endl; if (!metaClass->baseClass()) { s << INDENT << "TypeResolver* typeResolver = TypeResolver::get(typeid(*reinterpret_cast<" @@ -3353,7 +3353,7 @@ void CppGenerator::writeTypeDiscoveryFunction(QTextStream& s, const AbstractMeta s << INDENT << "if (typeResolver)" << endl; { Indentation indent(INDENT); - s << INDENT << "return reinterpret_cast(typeResolver->pythonType());" << endl; + s << INDENT << "return reinterpret_cast(typeResolver->pythonType());" << endl; } } else if (!polymorphicExpr.isEmpty()) { polymorphicExpr = polymorphicExpr.replace("%1", " reinterpret_cast<"+metaClass->qualifiedCppName()+"*>(cptr)"); @@ -3368,7 +3368,7 @@ void CppGenerator::writeTypeDiscoveryFunction(QTextStream& s, const AbstractMeta if (ancestor->baseClass()) continue; if (ancestor->isPolymorphic()) { - s << INDENT << "if (instanceType == reinterpret_cast(Shiboken::SbkType<" + s << INDENT << "if (instanceType == reinterpret_cast(Shiboken::SbkType<" << ancestor->qualifiedCppName() << " >()) && dynamic_cast<" << metaClass->qualifiedCppName() << "*>(reinterpret_cast<"<< ancestor->qualifiedCppName() << "*>(cptr)))" << endl; Indentation indent(INDENT); @@ -3675,7 +3675,7 @@ void CppGenerator::finishGeneration() s << INDENT << "}" << endl << endl; } - s << INDENT << "Shiboken::initShiboken();" << endl; + s << INDENT << "Shiboken::init();" << endl; s << INDENT << "PyObject* module = Py_InitModule(\"" << moduleName() << "\", "; s << moduleName() << "_methods);" << endl << endl; @@ -3689,7 +3689,7 @@ void CppGenerator::finishGeneration() if (!extendedConverters.isEmpty()) { s << INDENT << "// Initialize extended Converters" << endl; - s << INDENT << "SbkObjectType* shiboType;" << endl << endl; + s << INDENT << "SbkBaseType* shiboType;" << endl << endl; } foreach (const TypeEntry* externalType, extendedConverters.keys()) { writeExtendedConverterInitialization(s, externalType, extendedConverters[externalType]); diff --git a/generator/headergenerator.cpp b/generator/headergenerator.cpp index d9560d2a..590aea38 100644 --- a/generator/headergenerator.cpp +++ b/generator/headergenerator.cpp @@ -434,7 +434,7 @@ void HeaderGenerator::finishGeneration() s << INDENT << metaClass->qualifiedCppName() << "* value = const_cast<" << metaClass->qualifiedCppName() << "* >(cppobj);" << endl; s << INDENT << "if (!isExactType)" << endl; s << INDENT << INDENT << "typeName = typeid(*value).name();" << endl; - s << INDENT << "PyObject* pyObj = Shiboken::Wrapper::newObject(reinterpret_cast(SbkType<" << metaClass->qualifiedCppName() << " >())," + s << INDENT << "PyObject* pyObj = Shiboken::Wrapper::newObject(reinterpret_cast(SbkType<" << metaClass->qualifiedCppName() << " >())," << "value, hasOwnership, isExactType, typeName);" << endl; s << INDENT << "PySide::Signal::updateSourceObject(pyObj);" << endl; s << INDENT << "return pyObj;" << endl; @@ -531,7 +531,7 @@ void HeaderGenerator::writeTypeConverterImpl(QTextStream& s, const TypeEntry* ty } - s << INDENT << "SbkObjectType* shiboType = reinterpret_cast(SbkType<"; + s << INDENT << "SbkBaseType* shiboType = reinterpret_cast(SbkType<"; s << type->name() << " >());" << endl; s << INDENT << "return "; bool isFirst = true; @@ -550,7 +550,7 @@ void HeaderGenerator::writeTypeConverterImpl(QTextStream& s, const TypeEntry* ty s << endl; { Indentation indent(INDENT); - s << INDENT << " || (shiboType->ext_isconvertible && shiboType->ext_isconvertible(pyobj));" << endl; + s << INDENT << " || (BaseType::isExternalConvertible(shiboType, pyobj));" << endl; } s << '}' << endl << endl; diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 37d1282a..39c18c3e 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -34,16 +34,16 @@ extern "C" { -static void SbkObjectTypeDealloc(PyObject* pyObj); -static PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds); +static void SbkBaseTypeDealloc(PyObject* pyObj); +static PyObject* SbkBaseTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds); -PyTypeObject SbkObjectType_Type = { +PyTypeObject SbkBaseType_Type = { PyObject_HEAD_INIT(0) /*ob_size*/ 0, /*tp_name*/ "Shiboken.ObjectType", - /*tp_basicsize*/ sizeof(SbkObjectType), + /*tp_basicsize*/ sizeof(SbkBaseType), /*tp_itemsize*/ 0, - /*tp_dealloc*/ SbkObjectTypeDealloc, + /*tp_dealloc*/ SbkBaseTypeDealloc, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, @@ -76,7 +76,7 @@ PyTypeObject SbkObjectType_Type = { /*tp_dictoffset*/ 0, /*tp_init*/ 0, /*tp_alloc*/ 0, - /*tp_new*/ SbkObjectTypeTpNew, + /*tp_new*/ SbkBaseTypeTpNew, /*tp_free*/ 0, /*tp_is_gc*/ 0, /*tp_bases*/ 0, @@ -101,8 +101,8 @@ static PyGetSetDef SbkObjectGetSetList[] = { {0} // Sentinel }; -SbkObjectType SbkObject_Type = { { { - PyObject_HEAD_INIT(&SbkObjectType_Type) +SbkBaseType SbkObject_Type = { { { + PyObject_HEAD_INIT(&SbkBaseType_Type) /*ob_size*/ 0, /*tp_name*/ "Shiboken.Object", /*tp_basicsize*/ sizeof(SbkObject), @@ -149,12 +149,7 @@ SbkObjectType SbkObject_Type = { { { /*tp_subclasses*/ 0, /*tp_weaklist*/ 0 }, }, - /*mi_offsets*/ 0, - /*mi_init*/ 0, - /*mi_specialcast*/ 0, - /*type_name_func*/ 0, - /*ext_isconvertible*/ 0, - /*ext_tocpp*/ 0 + /*priv_data*/ 0 }; @@ -166,12 +161,12 @@ void SbkDeallocWrapper(PyObject* pyObj) // If I have ownership and is valid delete C++ pointer if (sbkObj->d->hasOwnership && sbkObj->d->validCppObject) { - SbkObjectType* sbkType = reinterpret_cast(pyObj->ob_type); - if (sbkType->is_multicpp) { + SbkBaseType* sbkType = reinterpret_cast(pyObj->ob_type); + if (sbkType->d->is_multicpp) { Shiboken::DtorCallerVisitor visitor(sbkObj); Shiboken::walkThroughClassHierarchy(pyObj->ob_type, &visitor); } else { - sbkType->cpp_dtor(sbkObj->d->cptr[0]); + sbkType->d->cpp_dtor(sbkObj->d->cptr[0]); } } @@ -188,54 +183,64 @@ void SbkDeallocWrapperWithPrivateDtor(PyObject* self) Shiboken::Wrapper::deallocData(sbkObj); } -void SbkObjectTypeDealloc(PyObject* pyObj) +void SbkBaseTypeDealloc(PyObject* pyObj) { - SbkObjectType *sbkType = reinterpret_cast(pyObj->ob_type); + SbkBaseType *sbkType = reinterpret_cast(pyObj->ob_type); + if (!sbkType->d) + return; - if(sbkType->user_data && sbkType->d_func) { - sbkType->d_func(sbkType->user_data); - sbkType->user_data = 0; + if(sbkType->d->user_data && sbkType->d->d_func) { + sbkType->d->d_func(sbkType->d->user_data); + sbkType->d->user_data = 0; } + free(sbkType->d->original_name); + sbkType->d->original_name = 0; + delete sbkType->d; + sbkType->d = 0; } -PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds) +PyObject* SbkBaseTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds) { // The meta type creates a new type when the Python programmer extends a wrapped C++ class. - SbkObjectType* newType = reinterpret_cast(PyType_Type.tp_new(metatype, args, kwds)); + SbkBaseType* newType = reinterpret_cast(PyType_Type.tp_new(metatype, args, kwds)); if (!newType) return 0; - std::list bases = Shiboken::getCppBaseClasses(reinterpret_cast(newType)); + SbkBaseTypePrivate* d = new SbkBaseTypePrivate; + memset(d, 0, sizeof(SbkBaseTypePrivate)); + + std::list bases = Shiboken::getCppBaseClasses(reinterpret_cast(newType)); if (bases.size() == 1) { - SbkObjectType* parentType = bases.front(); - newType->mi_offsets = parentType->mi_offsets; - newType->mi_init = parentType->mi_init; - newType->mi_specialcast = parentType->mi_specialcast; - newType->ext_isconvertible = parentType->ext_isconvertible; - newType->ext_tocpp = parentType->ext_tocpp; - newType->type_discovery = parentType->type_discovery; - newType->obj_copier = parentType->obj_copier; - newType->cpp_dtor = parentType->cpp_dtor; - newType->is_multicpp = 0; + SbkBaseTypePrivate* parentType = bases.front()->d; + d->mi_offsets = parentType->mi_offsets; + d->mi_init = parentType->mi_init; + d->mi_specialcast = parentType->mi_specialcast; + d->ext_isconvertible = parentType->ext_isconvertible; + d->ext_tocpp = parentType->ext_tocpp; + d->type_discovery = parentType->type_discovery; + d->obj_copier = parentType->obj_copier; + d->cpp_dtor = parentType->cpp_dtor; + d->is_multicpp = 0; } else { - newType->mi_offsets = 0; - newType->mi_init = 0; - newType->mi_specialcast = 0; - newType->ext_isconvertible = 0; - newType->ext_tocpp = 0; - newType->type_discovery = 0; - newType->obj_copier = 0; - newType->cpp_dtor = 0; - newType->is_multicpp = 1; + d->mi_offsets = 0; + d->mi_init = 0; + d->mi_specialcast = 0; + d->ext_isconvertible = 0; + d->ext_tocpp = 0; + d->type_discovery = 0; + d->obj_copier = 0; + d->cpp_dtor = 0; + d->is_multicpp = 1; } if (bases.size() == 1) - newType->original_name = bases.front()->original_name; + d->original_name = strdup(bases.front()->d->original_name); else - newType->original_name = "object"; - newType->user_data = 0; - newType->d_func = 0; - newType->is_user_type = 1; + d->original_name = strdup("object"); + d->user_data = 0; + d->d_func = 0; + d->is_user_type = 1; + newType->d = d; return reinterpret_cast(newType); } @@ -244,8 +249,8 @@ PyObject* SbkObjectTpNew(PyTypeObject* subtype, PyObject*, PyObject*) SbkObject* self = reinterpret_cast(subtype->tp_alloc(subtype, 0)); self->d = new SbkObjectPrivate; - SbkObjectType* sbkType = reinterpret_cast(subtype); - int numBases = sbkType->is_multicpp ? Shiboken::getNumberOfCppBaseClasses(subtype) : 1; + SbkBaseType* sbkType = reinterpret_cast(subtype); + int numBases = ((sbkType->d && sbkType->d->is_multicpp) ? Shiboken::getNumberOfCppBaseClasses(subtype) : 1); self->d->cptr = new void*[numBases]; std::memset(self->d->cptr, 0, sizeof(void*)*numBases); self->d->hasOwnership = 1; @@ -274,11 +279,11 @@ void walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visi for (int i = 0; i < numBases; ++i) { PyTypeObject* type = reinterpret_cast(PyTuple_GET_ITEM(bases, i)); - if (type->ob_type != &SbkObjectType_Type) { + if (type->ob_type != &SbkBaseType_Type) { continue; } else { - SbkObjectType* sbkType = reinterpret_cast(type); - if (sbkType->is_user_type) + SbkBaseType* sbkType = reinterpret_cast(type); + if (sbkType->d->is_user_type) walkThroughClassHierarchy(type, visitor); else visitor->visit(sbkType); @@ -288,61 +293,6 @@ void walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visi } } -void setTypeUserData(SbkObject* wrapper, void *user_data, DeleteUserDataFunc d_func) -{ - SbkObjectType* ob_type = reinterpret_cast(wrapper->ob_type); - if (ob_type->user_data) - ob_type->d_func(ob_type->user_data); - - ob_type->d_func = d_func; - ob_type->user_data = user_data; -} - -void* getTypeUserData(SbkObject* wrapper) -{ - return reinterpret_cast(wrapper->ob_type)->user_data; -} - -void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append) -{ - - bool isNone = (!referredObject || (referredObject == Py_None)); - - if (!self->d->referredObjects) - self->d->referredObjects = new Shiboken::RefCountMap; - - RefCountMap& refCountMap = *(self->d->referredObjects); - if (!isNone) - incRefPyObject(referredObject); - - RefCountMap::iterator iter = refCountMap.find(key); - if (!append && (iter != refCountMap.end())) { - decRefPyObjectList(iter->second); - refCountMap.erase(iter); - } - - if (!isNone) { - std::list values = splitPyObject(referredObject); - if (append && (iter != refCountMap.end())) - refCountMap[key].insert(refCountMap[key].end(), values.begin(), values.end()); - else - refCountMap[key] = values; - } -} - -void clearReferences(SbkObject* self) -{ - if (!self->d->referredObjects) - return; - - RefCountMap& refCountMap = *(self->d->referredObjects); - RefCountMap::iterator iter; - for (iter = refCountMap.begin(); iter != refCountMap.end(); ++iter) - decRefPyObjectList(iter->second); - delete self->d->referredObjects; - self->d->referredObjects = 0; -} - bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr) { Shiboken::AutoDecRef module(PyImport_ImportModule(moduleName)); @@ -361,13 +311,13 @@ bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr) // Wrapper metatype and base type ---------------------------------------------------------- -void DtorCallerVisitor::visit(SbkObjectType* node) +void DtorCallerVisitor::visit(SbkBaseType* node) { - node->cpp_dtor(m_pyObj->d->cptr[m_count]); + node->d->cpp_dtor(m_pyObj->d->cptr[m_count]); m_count++; } -void initShiboken() +void init() { static bool shibokenAlreadInitialised = false; if (shibokenAlreadInitialised) @@ -381,7 +331,7 @@ void initShiboken() if (PyType_Ready(&SbkEnumType_Type) < 0) Py_FatalError("[libshiboken] Failed to initialise Shiboken.SbkEnumType metatype."); - if (PyType_Ready(&SbkObjectType_Type) < 0) + if (PyType_Ready(&SbkBaseType_Type) < 0) Py_FatalError("[libshiboken] Failed to initialise Shiboken.BaseWrapperType metatype."); if (PyType_Ready((PyTypeObject *)&SbkObject_Type) < 0) @@ -435,7 +385,7 @@ class FindBaseTypeVisitor : public HierarchyVisitor { public: FindBaseTypeVisitor(PyTypeObject* typeToFind) : m_found(false), m_typeToFind(typeToFind) {} - virtual void visit(SbkObjectType* node) + virtual void visit(SbkBaseType* node) { if (reinterpret_cast(node) == m_typeToFind) { m_found = true; @@ -449,17 +399,6 @@ class FindBaseTypeVisitor : public HierarchyVisitor PyTypeObject* m_typeToFind; }; -bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType) -{ - FindBaseTypeVisitor visitor(ctorType); - walkThroughClassHierarchy(myType, &visitor); - if (!visitor.found()) { - PyErr_Format(PyExc_TypeError, "%s isn't a direct base class of %s", ctorType->tp_name, myType->tp_name); - return false; - } - return true; -} - std::list splitPyObject(PyObject* pyObj) { std::list result; @@ -468,7 +407,7 @@ std::list splitPyObject(PyObject* pyObj) if (!lst.isNull()) { for(int i = 0, i_max = PySequence_Fast_GET_SIZE(lst.object()); i < i_max; i++) { PyObject* item = PySequence_Fast_GET_ITEM(lst.object(), i); - if (isShibokenType(item)) + if (Wrapper::checkType(item)) result.push_back(reinterpret_cast(item)); } } @@ -498,9 +437,145 @@ static void decRefPyObjectList(const std::list& lst) } } +namespace BaseType +{ + +bool checkType(PyTypeObject* type) +{ + return type->ob_type == &SbkBaseType_Type; +} + +bool isUserType(PyTypeObject* type) +{ + return BaseType::checkType(type) && reinterpret_cast(type)->d->is_user_type; +} + +bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType) +{ + FindBaseTypeVisitor visitor(ctorType); + walkThroughClassHierarchy(myType, &visitor); + if (!visitor.found()) { + PyErr_Format(PyExc_TypeError, "%s isn't a direct base class of %s", ctorType->tp_name, myType->tp_name); + return false; + } + return true; +} + +void* copy(SbkBaseType* self, const void* obj) +{ + return self->d->obj_copier(obj); +} + +void setCopyFunction(SbkBaseType* self, ObjectCopierFunction func) +{ + self->d->obj_copier = func; +} + +bool hasExternalCppConversions(SbkBaseType* self) +{ + return self->d->ext_tocpp; +} + +void* callExternalCppConversion(SbkBaseType* self, PyObject* obj) +{ + return self->d->ext_tocpp(obj); +} + +void setExternalCppConversionFunction(SbkBaseType* self, ExtendedToCppFunc func) +{ + self->d->ext_tocpp = func; +} + +void setExternalIsConvertibleFunction(SbkBaseType* self, ExtendedIsConvertibleFunc func) +{ + self->d->ext_isconvertible = func; +} + +bool isExternalConvertible(SbkBaseType* self, PyObject* obj) +{ + return self->d->ext_isconvertible && self->d->ext_isconvertible(obj); +} + +bool hasCast(SbkBaseType* self) +{ + return self->d->mi_specialcast; +} + +void* cast(SbkBaseType* self, SbkObject* obj, PyTypeObject *target) +{ + return self->d->mi_specialcast(Wrapper::cppPointer(obj, target), reinterpret_cast(target)); +} + +void setCastFunction(SbkBaseType* self, SpecialCastFunction func) +{ + self->d->mi_specialcast = func; +} + +void setOriginalName(SbkBaseType* self, const char* name) +{ + if (self->d->original_name) + free(self->d->original_name); + self->d->original_name = strdup(name); +} + +const char* getOriginalName(SbkBaseType* self) +{ + return self->d->original_name; +} + +void setTypeDiscoveryFunction(SbkBaseType* self, TypeDiscoveryFunc func) +{ + self->d->type_discovery = func; +} + +TypeDiscoveryFunc getTypeDiscoveryFunction(SbkBaseType* self) +{ + return self->d->type_discovery; +} + +void copyMultimpleheritance(SbkBaseType* self, SbkBaseType* other) +{ + self->d->mi_init = other->d->mi_init; + self->d->mi_offsets = other->d->mi_offsets; + self->d->mi_specialcast = other->d->mi_specialcast; +} + +void setMultipleIheritanceFunction(SbkBaseType* self, MultipleInheritanceInitFunction function) +{ + self->d->mi_init = function; +} + +MultipleInheritanceInitFunction getMultipleIheritanceFunction(SbkBaseType* self) +{ + return self->d->mi_init; +} + +void setDestructorFunction(SbkBaseType* self, ObjectDestructor func) +{ + self->d->cpp_dtor = func; +} + +void initPrivateData(SbkBaseType* self) +{ + self->d = new SbkBaseTypePrivate; + memset(self->d, 0, sizeof(SbkBaseTypePrivate)); +} + +} // namespace BaseType + namespace Wrapper { +bool checkType(PyObject* pyObj) +{ + return BaseType::checkType(pyObj->ob_type); +} + +bool isUserType(PyObject* pyObj) +{ + return BaseType::isUserType(pyObj->ob_type); +} + static void setSequenceOwnership(PyObject* pyObj, bool owner) { if (PySequence_Check(pyObj)) { @@ -512,7 +587,7 @@ static void setSequenceOwnership(PyObject* pyObj, bool owner) else releaseOwnership(*it); } - } else if (isShibokenType(pyObj)) { + } else if (Wrapper::checkType(pyObj)) { if (owner) getOwnership(reinterpret_cast(pyObj)); else @@ -665,7 +740,7 @@ void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType) { PyTypeObject* type = pyObj->ob_type; int idx = 0; - if (reinterpret_cast(type)->is_multicpp) + if (reinterpret_cast(type)->d->is_multicpp) idx = getTypeIndexOnHierarchy(type, desiredType); return pyObj->d->cptr[idx]; } @@ -673,7 +748,7 @@ void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType) bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr) { int idx = 0; - if (reinterpret_cast(sbkObj->ob_type)->is_multicpp) + if (reinterpret_cast(sbkObj->ob_type)->d->is_multicpp) idx = getTypeIndexOnHierarchy(sbkObj->ob_type, desiredType); bool alreadyInitialized = sbkObj->d->cptr[idx]; @@ -688,7 +763,7 @@ bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr) bool isValid(PyObject* pyObj) { if (!pyObj || pyObj == Py_None - || pyObj->ob_type->ob_type != &SbkObjectType_Type + || pyObj->ob_type->ob_type != &SbkBaseType_Type || ((SbkObject*)pyObj)->d->validCppObject) { return true; } @@ -696,7 +771,7 @@ bool isValid(PyObject* pyObj) return false; } -PyObject* newObject(SbkObjectType* instanceType, +PyObject* newObject(SbkBaseType* instanceType, void* cptr, bool hasOwnership, bool isExactType, @@ -708,7 +783,7 @@ PyObject* newObject(SbkObjectType* instanceType, if (typeName) { tr = TypeResolver::get(typeName); if (tr) - instanceType = reinterpret_cast(tr->pythonType()); + instanceType = reinterpret_cast(tr->pythonType()); } if (!tr) instanceType = BindingManager::instance().resolveType(cptr, instanceType); @@ -802,7 +877,7 @@ void setParent(PyObject* parent, PyObject* child) * so if you pass this class to someone that takes the ownership, we CAN'T enter in this if, but hey! QString * follows the sequence protocol. */ - if (PySequence_Check(child) && !isShibokenType(child)) { + if (PySequence_Check(child) && !Wrapper::checkType(child)) { Shiboken::AutoDecRef seq(PySequence_Fast(child, 0)); for (int i = 0, max = PySequence_Size(seq); i < max; ++i) setParent(parent, PySequence_Fast_GET_ITEM(seq.object(), i)); @@ -874,6 +949,61 @@ void deallocData(SbkObject* self) Py_TYPE(self)->tp_free(self); } +void setTypeUserData(SbkObject* wrapper, void *user_data, DeleteUserDataFunc d_func) +{ + SbkBaseType* ob_type = reinterpret_cast(wrapper->ob_type); + if (ob_type->d->user_data) + ob_type->d->d_func(ob_type->d->user_data); + + ob_type->d->d_func = d_func; + ob_type->d->user_data = user_data; +} + +void* getTypeUserData(SbkObject* wrapper) +{ + return reinterpret_cast(wrapper->ob_type)->d->user_data; +} + +void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append) +{ + + bool isNone = (!referredObject || (referredObject == Py_None)); + + if (!self->d->referredObjects) + self->d->referredObjects = new Shiboken::RefCountMap; + + RefCountMap& refCountMap = *(self->d->referredObjects); + if (!isNone) + incRefPyObject(referredObject); + + RefCountMap::iterator iter = refCountMap.find(key); + if (!append && (iter != refCountMap.end())) { + decRefPyObjectList(iter->second); + refCountMap.erase(iter); + } + + if (!isNone) { + std::list values = splitPyObject(referredObject); + if (append && (iter != refCountMap.end())) + refCountMap[key].insert(refCountMap[key].end(), values.begin(), values.end()); + else + refCountMap[key] = values; + } +} + +void clearReferences(SbkObject* self) +{ + if (!self->d->referredObjects) + return; + + RefCountMap& refCountMap = *(self->d->referredObjects); + RefCountMap::iterator iter; + for (iter = refCountMap.begin(); iter != refCountMap.end(); ++iter) + decRefPyObjectList(iter->second); + delete self->d->referredObjects; + self->d->referredObjects = 0; +} + } // namespace Wrapper } // namespace Shiboken diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index f723a7a9..aa1301df 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -51,7 +51,7 @@ struct LIBSHIBOKEN_API SbkObject LIBSHIBOKEN_API void SbkDeallocWrapper(PyObject* pyObj); LIBSHIBOKEN_API void SbkDeallocWrapperWithPrivateDtor(PyObject* self); -struct SbkObjectType; +struct SbkBaseType; /// Function signature for the multiple inheritance information initializers that should be provided by classes with multiple inheritance. typedef int* (*MultipleInheritanceInitFunction)(const void*); @@ -61,9 +61,9 @@ typedef int* (*MultipleInheritanceInitFunction)(const void*); * part of a multiple inheritance hierarchy. * The implementation of this function is auto generated by the generator and you don't need to care about it. */ -typedef void* (*SpecialCastFunction)(void*, SbkObjectType*); +typedef void* (*SpecialCastFunction)(void*, SbkBaseType*); typedef void* (*ObjectCopierFunction)(const void*); -typedef SbkObjectType* (*TypeDiscoveryFunc)(void*, SbkObjectType*); +typedef SbkBaseType* (*TypeDiscoveryFunc)(void*, SbkBaseType*); typedef void* (*ExtendedToCppFunc)(PyObject*); typedef bool (*ExtendedIsConvertibleFunc)(PyObject*); @@ -71,34 +71,18 @@ typedef bool (*ExtendedIsConvertibleFunc)(PyObject*); // Used in userdata dealloc function typedef void (*DeleteUserDataFunc)(void*); -extern LIBSHIBOKEN_API PyTypeObject SbkObjectType_Type; -extern LIBSHIBOKEN_API SbkObjectType SbkObject_Type; +typedef void (*ObjectDestructor)(void*); +extern LIBSHIBOKEN_API PyTypeObject SbkBaseType_Type; +extern LIBSHIBOKEN_API SbkBaseType SbkObject_Type; + + +struct SbkBaseTypePrivate; /// PyTypeObject extended with C++ multiple inheritance information. -struct LIBSHIBOKEN_API SbkObjectType +struct LIBSHIBOKEN_API SbkBaseType { PyHeapTypeObject super; - int* mi_offsets; - MultipleInheritanceInitFunction mi_init; - /// Special cast function, null if this class doesn't have multiple inheritance. - SpecialCastFunction mi_specialcast; - TypeDiscoveryFunc type_discovery; - ObjectCopierFunction obj_copier; - /// Extended "isConvertible" function to be used when a conversion operator is defined in another module. - ExtendedIsConvertibleFunc ext_isconvertible; - /// Extended "toCpp" function to be used when a conversion operator is defined in another module. - ExtendedToCppFunc ext_tocpp; - /// Pointer to a function responsible for deletetion of the C++ instance calling the proper destructor. - void (*cpp_dtor)(void*); - /// True if this type holds two or more C++ instances, e.g.: a Python class which inherits from two C++ classes. - int is_multicpp:1; - /// True if this type was definied by the user. - int is_user_type:1; - /// C++ name - const char* original_name; - /// Type user data - void *user_data; - DeleteUserDataFunc d_func; + SbkBaseTypePrivate* d; }; LIBSHIBOKEN_API PyObject* SbkObjectTpNew(PyTypeObject* subtype, PyObject*, PyObject*); @@ -111,94 +95,109 @@ namespace Shiboken /** * Init shiboken library. */ -LIBSHIBOKEN_API void initShiboken(); +LIBSHIBOKEN_API void init(); -/** -* Returns true if the object is an instance of a type created by the Shiboken generator. -*/ -inline bool isShibokenType(PyObject*& pyObj) + +/// Delete the class T allocated on \p cptr. +template +void callCppDestructor(void* cptr) { - return pyObj->ob_type->ob_type == &SbkObjectType_Type; + delete reinterpret_cast(cptr); } +LIBSHIBOKEN_API bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr); +LIBSHIBOKEN_API void setErrorAboutWrongArguments(PyObject* args, const char* funcName, const char** cppOverloads); + +namespace BaseType { + /** -* Returns true if this object is an instance of an user defined type derived from an Shiboken type. +* Returns true if the object is an instance of a type created by the Shiboken generator. */ -inline bool isUserType(PyObject*& pyObj) -{ - return isShibokenType(pyObj) && reinterpret_cast(pyObj->ob_type)->is_user_type; -} +LIBSHIBOKEN_API bool checkType(PyTypeObject* pyObj); /** - * Get/Set Userdata in type class - */ -LIBSHIBOKEN_API void setTypeUserData(SbkObject* wrapper, void* user_data, DeleteUserDataFunc d_func); -LIBSHIBOKEN_API void* getTypeUserData(SbkObject* wrapper); +* Returns true if this object is an instance of an user defined type derived from an Shiboken type. +*/ +LIBSHIBOKEN_API bool isUserType(PyTypeObject* pyObj); /** * Returns true if the constructor of \p ctorType can be called for a instance of type \p myType. * \note This function set a python error when returning false. */ -LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType); +LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType); /** - * Increments the reference count of the referred Python object. - * A previous Python object in the same position identified by the 'key' parameter - * will have its reference counter decremented automatically when replaced. - * All the kept references should be decremented when the Python wrapper indicated by - * 'self' dies. - * No checking is done for any of the passed arguments, since it is meant to be used - * by generated code it is supposed that the generator is correct. - * \param self the wrapper instance that keeps references to other objects. - * \param key a key that identifies the C++ method signature and argument where the referredObject came from. - * \parem referredObject the object whose reference is used by the self object. - */ -LIBSHIBOKEN_API void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append=false); + * Call copy function for the object type + **/ +LIBSHIBOKEN_API void* copy(SbkBaseType* self, const void *obj); +LIBSHIBOKEN_API void setCopyFunction(SbkBaseType* self, ObjectCopierFunction func); -/// Delete the class T allocated on \p cptr. -template -void callCppDestructor(void* cptr) -{ - delete reinterpret_cast(cptr); -} +LIBSHIBOKEN_API void setExternalCppConversionFunction(SbkBaseType* self, ExtendedToCppFunc func); +LIBSHIBOKEN_API void setExternalIsConvertibleFunction(SbkBaseType* self, ExtendedIsConvertibleFunc func); +LIBSHIBOKEN_API bool hasExternalCppConversions(SbkBaseType* self); +LIBSHIBOKEN_API bool isExternalConvertible(SbkBaseType* self, PyObject* obj); +LIBSHIBOKEN_API void* callExternalCppConversion(SbkBaseType* self, PyObject* obj); + +LIBSHIBOKEN_API bool hasCast(SbkBaseType* self); +LIBSHIBOKEN_API void* cast(SbkBaseType* self, SbkObject* obj, PyTypeObject* target); +LIBSHIBOKEN_API void setCastFunction(SbkBaseType* self, SpecialCastFunction func); + +LIBSHIBOKEN_API void setOriginalName(SbkBaseType* self, const char* name); +LIBSHIBOKEN_API const char* getOriginalName(SbkBaseType* self); + +LIBSHIBOKEN_API void setTypeDiscoveryFunction(SbkBaseType* self, TypeDiscoveryFunc func); +LIBSHIBOKEN_API TypeDiscoveryFunc getTypeDiscoveryFunction(SbkBaseType* self); + +LIBSHIBOKEN_API void copyMultimpleheritance(SbkBaseType* self, SbkBaseType* other); +LIBSHIBOKEN_API void setMultipleIheritanceFunction(SbkBaseType* self, MultipleInheritanceInitFunction func); +LIBSHIBOKEN_API MultipleInheritanceInitFunction getMultipleIheritanceFunction(SbkBaseType* self); -LIBSHIBOKEN_API bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr); -LIBSHIBOKEN_API void setErrorAboutWrongArguments(PyObject* args, const char* funcName, const char** cppOverloads); +LIBSHIBOKEN_API void setDestructorFunction(SbkBaseType* self, ObjectDestructor func); + +LIBSHIBOKEN_API void initPrivateData(SbkBaseType* self); +} namespace Wrapper { -LIBSHIBOKEN_API PyObject* newObject(SbkObjectType* instanceType, - void* cptr, - bool hasOwnership = true, - bool isExactType = false, - const char* typeName = 0); +/** +* Returns true if the object is an instance of a type created by the Shiboken generator. +*/ +LIBSHIBOKEN_API bool checkType(PyObject* pyObj); +LIBSHIBOKEN_API bool isUserType(PyObject* pyObj); + -LIBSHIBOKEN_API void setValidCpp(SbkObject* pyObj, bool value); -LIBSHIBOKEN_API void setHasCppWrapper(SbkObject* pyObj, bool value); -LIBSHIBOKEN_API bool hasCppWrapper(SbkObject* pyObj); +LIBSHIBOKEN_API PyObject* newObject(SbkBaseType* instanceType, + void* cptr, + bool hasOwnership = true, + bool isExactType = false, + const char* typeName = 0); -LIBSHIBOKEN_API bool hasOwnership(SbkObject* pyObj); -LIBSHIBOKEN_API void getOwnership(PyObject* pyObj); -LIBSHIBOKEN_API void getOwnership(SbkObject* pyObj); -LIBSHIBOKEN_API void releaseOwnership(PyObject* pyObj); -LIBSHIBOKEN_API void releaseOwnership(SbkObject* pyObj); +LIBSHIBOKEN_API void setValidCpp(SbkObject* pyObj, bool value); +LIBSHIBOKEN_API void setHasCppWrapper(SbkObject* pyObj, bool value); +LIBSHIBOKEN_API bool hasCppWrapper(SbkObject* pyObj); -LIBSHIBOKEN_API bool hasParentInfo(SbkObject* pyObj); +LIBSHIBOKEN_API bool hasOwnership(SbkObject* pyObj); +LIBSHIBOKEN_API void getOwnership(PyObject* pyObj); +LIBSHIBOKEN_API void getOwnership(SbkObject* pyObj); +LIBSHIBOKEN_API void releaseOwnership(PyObject* pyObj); +LIBSHIBOKEN_API void releaseOwnership(SbkObject* pyObj); + +LIBSHIBOKEN_API bool hasParentInfo(SbkObject* pyObj); /** * Get the C++ pointer of type \p desiredType from a Python object. */ -LIBSHIBOKEN_API void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType); +LIBSHIBOKEN_API void* cppPointer(SbkObject* pyObj, PyTypeObject* desiredType); /** * Set the C++ pointer of type \p desiredType of a Python object. */ -LIBSHIBOKEN_API bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr); +LIBSHIBOKEN_API bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr); /** * Returns false and sets a Python RuntimeError if the Python wrapper is not marked as valid. */ -LIBSHIBOKEN_API bool isValid(PyObject* wrapper); +LIBSHIBOKEN_API bool isValid(PyObject* wrapper); /** * Set the parent of \p child to \p parent. @@ -206,39 +205,59 @@ LIBSHIBOKEN_API bool isValid(PyObject* wrapper); * \param parent the parent object, if null, the child will have no parents. * \param child the child. */ -LIBSHIBOKEN_API void setParent(PyObject* parent, PyObject* child); +LIBSHIBOKEN_API void setParent(PyObject* parent, PyObject* child); /** * Remove this child from their parent, if any. * \param child the child. */ -LIBSHIBOKEN_API void removeParent(SbkObject* child, bool giveOwnershipBack = true, bool keepReferenc = false); +LIBSHIBOKEN_API void removeParent(SbkObject* child, bool giveOwnershipBack = true, bool keepReferenc = false); /** * \internal This is an internal function called by SbkBaseWrapper_Dealloc, it's exported just for techinical reasons. * \note Do not call this function inside your bindings. */ -LIBSHIBOKEN_API void destroyParentInfo(SbkObject* obj, bool removeFromParent = true); +LIBSHIBOKEN_API void destroyParentInfo(SbkObject* obj, bool removeFromParent = true); /** * Mark the object as invalid */ -LIBSHIBOKEN_API void invalidate(SbkObject* self); +LIBSHIBOKEN_API void invalidate(SbkObject* self); /** * Help function can be used to invalida a sequence of object **/ -LIBSHIBOKEN_API void invalidate(PyObject* pyobj); +LIBSHIBOKEN_API void invalidate(PyObject* pyobj); /** * Make the object valid again */ -LIBSHIBOKEN_API void makeValid(SbkObject* self); +LIBSHIBOKEN_API void makeValid(SbkObject* self); /** * Destroy any data in Shiboken structure and c++ pointer if the pyboject has the ownership **/ -LIBSHIBOKEN_API void destroy(SbkObject* self); +LIBSHIBOKEN_API void destroy(SbkObject* self); + +/** + * Get/Set Userdata in type class + */ +LIBSHIBOKEN_API void setTypeUserData(SbkObject* wrapper, void* user_data, DeleteUserDataFunc d_func); +LIBSHIBOKEN_API void* getTypeUserData(SbkObject* wrapper); + +/** + * Increments the reference count of the referred Python object. + * A previous Python object in the same position identified by the 'key' parameter + * will have its reference counter decremented automatically when replaced. + * All the kept references should be decremented when the Python wrapper indicated by + * 'self' dies. + * No checking is done for any of the passed arguments, since it is meant to be used + * by generated code it is supposed that the generator is correct. + * \param self the wrapper instance that keeps references to other objects. + * \param key a key that identifies the C++ method signature and argument where the referredObject came from. + * \parem referredObject the object whose reference is used by the self object. + */ +LIBSHIBOKEN_API void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append=false); } // namespace Wrapper diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h index 748ce2dc..702fdbd0 100644 --- a/libshiboken/basewrapper_p.h +++ b/libshiboken/basewrapper_p.h @@ -28,7 +28,7 @@ #include struct SbkObject; -struct SbkObjectType; +struct SbkBaseType; namespace Shiboken { @@ -80,6 +80,34 @@ struct SbkObjectPrivate Shiboken::RefCountMap* referredObjects; }; + +struct SbkBaseTypePrivate +{ + int* mi_offsets; + MultipleInheritanceInitFunction mi_init; + + /// Special cast function, null if this class doesn't have multiple inheritance. + SpecialCastFunction mi_specialcast; + TypeDiscoveryFunc type_discovery; + ObjectCopierFunction obj_copier; + /// Extended "isConvertible" function to be used when a conversion operator is defined in another module. + ExtendedIsConvertibleFunc ext_isconvertible; + /// Extended "toCpp" function to be used when a conversion operator is defined in another module. + ExtendedToCppFunc ext_tocpp; + /// Pointer to a function responsible for deletetion of the C++ instance calling the proper destructor. + ObjectDestructor cpp_dtor; + /// True if this type holds two or more C++ instances, e.g.: a Python class which inherits from two C++ classes. + int is_multicpp:1; + /// True if this type was definied by the user. + int is_user_type:1; + /// C++ name + char* original_name; + /// Type user data + void *user_data; + DeleteUserDataFunc d_func; +}; + + } // extern "C" namespace Shiboken @@ -97,7 +125,7 @@ class HierarchyVisitor public: HierarchyVisitor() : m_wasFinished(false) {} virtual ~HierarchyVisitor() {} - virtual void visit(SbkObjectType* node) = 0; + virtual void visit(SbkBaseType* node) = 0; void finish() { m_wasFinished = true; }; bool wasFinished() const { return m_wasFinished; } private: @@ -109,7 +137,7 @@ class BaseCountVisitor : public HierarchyVisitor public: BaseCountVisitor() : m_count(0) {} - void visit(SbkObjectType*) + void visit(SbkBaseType*) { m_count++; } @@ -124,21 +152,21 @@ class BaseAccumulatorVisitor : public HierarchyVisitor public: BaseAccumulatorVisitor() {} - void visit(SbkObjectType* node) + void visit(SbkBaseType* node) { m_bases.push_back(node); } - std::list bases() const { return m_bases; } + std::list bases() const { return m_bases; } private: - std::list m_bases; + std::list m_bases; }; class GetIndexVisitor : public HierarchyVisitor { public: GetIndexVisitor(PyTypeObject* desiredType) : m_index(-1), m_desiredType(desiredType) {} - virtual void visit(SbkObjectType* node) + virtual void visit(SbkBaseType* node) { m_index++; if (PyType_IsSubtype(reinterpret_cast(node), m_desiredType)) @@ -155,7 +183,7 @@ class DtorCallerVisitor : public HierarchyVisitor { public: DtorCallerVisitor(SbkObject* pyObj) : m_count(0), m_pyObj(pyObj) {} - void visit(SbkObjectType* node); + void visit(SbkBaseType* node); private: int m_count; SbkObject* m_pyObj; @@ -183,21 +211,21 @@ inline int getNumberOfCppBaseClasses(PyTypeObject* baseType) return visitor.count(); } -inline std::list getCppBaseClasses(PyTypeObject* baseType) +inline std::list getCppBaseClasses(PyTypeObject* baseType) { BaseAccumulatorVisitor visitor; walkThroughClassHierarchy(baseType, &visitor); return visitor.bases(); } +namespace Wrapper +{ /** * Decrements the reference counters of every object referred by self. * \param self the wrapper instance that keeps references to other objects. */ void clearReferences(SbkObject* self); -namespace Wrapper -{ /** * Destroy internal data **/ diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index b56cceed..3742f6fe 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -37,8 +37,8 @@ typedef google::dense_hash_map WrapperMap; class Graph { public: - typedef std::list NodeList; - typedef google::dense_hash_map Edges; + typedef std::list NodeList; + typedef google::dense_hash_map Edges; Edges m_edges; @@ -47,7 +47,7 @@ class Graph m_edges.set_empty_key(0); } - void addEdge(SbkObjectType* from, SbkObjectType* to) + void addEdge(SbkBaseType* from, SbkBaseType* to) { m_edges[from].push_back(to); } @@ -61,7 +61,7 @@ class Graph Edges::const_iterator i = m_edges.begin(); for (; i != m_edges.end(); ++i) { - SbkObjectType* node1 = i->first; + SbkBaseType* node1 = i->first; const NodeList& nodeList = i->second; NodeList::const_iterator j = nodeList.begin(); for (; j != nodeList.end(); ++j) @@ -71,19 +71,19 @@ class Graph } #endif - SbkObjectType* identifyType(void* cptr, SbkObjectType* type, SbkObjectType* baseType) const + SbkBaseType* identifyType(void* cptr, SbkBaseType* type, SbkBaseType* baseType) const { Edges::const_iterator edgesIt = m_edges.find(type); if (edgesIt != m_edges.end()) { const NodeList& adjNodes = m_edges.find(type)->second; NodeList::const_iterator i = adjNodes.begin(); for (; i != adjNodes.end(); ++i) { - SbkObjectType* newType = identifyType(cptr, *i, baseType); + SbkBaseType* newType = identifyType(cptr, *i, baseType); if (newType) return newType; } } - return type->type_discovery ? type->type_discovery(cptr, baseType) : 0; + return ((type->d && type->d->type_discovery) ? type->d->type_discovery(cptr, baseType) : 0); } }; @@ -166,13 +166,17 @@ bool BindingManager::hasWrapper(const void* cptr) void BindingManager::registerWrapper(SbkObject* pyObj, void* cptr) { - SbkObjectType* instanceType = reinterpret_cast(pyObj->ob_type); + SbkBaseType* instanceType = reinterpret_cast(pyObj->ob_type); + SbkBaseTypePrivate* d = instanceType->d; - if (instanceType->mi_init && !instanceType->mi_offsets) - instanceType->mi_offsets = instanceType->mi_init(cptr); + if (!d) + return; + + if (d->mi_init && !d->mi_offsets) + d->mi_offsets = d->mi_init(cptr); m_d->assignWrapper(pyObj, cptr); - if (instanceType->mi_offsets) { - int* offset = instanceType->mi_offsets; + if (d->mi_offsets) { + int* offset = d->mi_offsets; while (*offset != -1) { if (*offset > 0) m_d->assignWrapper(pyObj, reinterpret_cast((std::size_t) cptr + (*offset))); @@ -183,15 +187,16 @@ void BindingManager::registerWrapper(SbkObject* pyObj, void* cptr) void BindingManager::releaseWrapper(SbkObject* sbkObj) { - SbkObjectType* sbkType = reinterpret_cast(sbkObj->ob_type); - int numBases = sbkType->is_multicpp ? getNumberOfCppBaseClasses(sbkObj->ob_type) : 1; + SbkBaseType* sbkType = reinterpret_cast(sbkObj->ob_type); + SbkBaseTypePrivate* d = sbkType->d; + int numBases = ((d && d->is_multicpp) ? getNumberOfCppBaseClasses(sbkObj->ob_type) : 1); void** cptrs = reinterpret_cast(sbkObj)->d->cptr; for (int i = 0; i < numBases; ++i) { void* cptr = cptrs[i]; m_d->releaseWrapper(cptr); - if (sbkType->mi_offsets) { - int* offset = sbkType->mi_offsets; + if (d && d->mi_offsets) { + int* offset = d->mi_offsets; while (*offset != -1) { if (*offset > 0) m_d->releaseWrapper((void*) ((std::size_t) cptr + (*offset))); @@ -250,14 +255,14 @@ PyObject* BindingManager::getOverride(const void* cptr, const char* methodName) return 0; } -void BindingManager::addClassInheritance(SbkObjectType* parent, SbkObjectType* child) +void BindingManager::addClassInheritance(SbkBaseType* parent, SbkBaseType* child) { m_d->classHierarchy.addEdge(parent, child); } -SbkObjectType* BindingManager::resolveType(void* cptr, SbkObjectType* type) +SbkBaseType* BindingManager::resolveType(void* cptr, SbkBaseType* type) { - SbkObjectType* identifiedType = m_d->classHierarchy.identifyType(cptr, type, type); + SbkBaseType* identifiedType = m_d->classHierarchy.identifyType(cptr, type, type); return identifiedType ? identifiedType : type; } diff --git a/libshiboken/bindingmanager.h b/libshiboken/bindingmanager.h index b6d4ac42..2ead2351 100644 --- a/libshiboken/bindingmanager.h +++ b/libshiboken/bindingmanager.h @@ -28,7 +28,7 @@ #include "shibokenmacros.h" struct SbkObject; -struct SbkObjectType; +struct SbkBaseType; namespace Shiboken { @@ -46,8 +46,8 @@ class LIBSHIBOKEN_API BindingManager SbkObject* retrieveWrapper(const void* cptr); PyObject* getOverride(const void* cptr, const char* methodName); - void addClassInheritance(SbkObjectType* parent, SbkObjectType* child); - SbkObjectType* resolveType(void* cptr, SbkObjectType* type); + void addClassInheritance(SbkBaseType* parent, SbkBaseType* child); + SbkBaseType* resolveType(void* cptr, SbkBaseType* type); std::set getAllPyObjects(); private: diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index 4d55ef0f..d6a3dd5e 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -99,7 +99,7 @@ struct CppObjectCopier { static inline T* copy(const T& obj) { - return reinterpret_cast(reinterpret_cast(SbkType())->obj_copier(&obj)); + return reinterpret_cast(BaseType::copy(reinterpret_cast(SbkType()), &obj)); } }; @@ -113,7 +113,7 @@ inline PyObject* createWrapper(const T* cppobj, bool hasOwnership = false, bool const char* typeName = 0; if (!isExactType) typeName = typeid(*const_cast(cppobj)).name(); - return Wrapper::newObject(reinterpret_cast(SbkType()), + return Wrapper::newObject(reinterpret_cast(SbkType()), const_cast(cppobj), hasOwnership, isExactType, typeName); } @@ -213,10 +213,8 @@ struct ValueTypeConverter { if (PyObject_TypeCheck(pyobj, SbkType())) return true; - SbkObjectType* shiboType = reinterpret_cast(SbkType()); - if (shiboType->ext_isconvertible) - return shiboType->ext_isconvertible(pyobj); - return false; + SbkBaseType* shiboType = reinterpret_cast(SbkType()); + return BaseType::isExternalConvertible(shiboType, pyobj); } static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } static inline PyObject* toPython(const T& cppobj) @@ -233,9 +231,9 @@ struct ValueTypeConverter static inline T toCpp(PyObject* pyobj) { if (!PyObject_TypeCheck(pyobj, SbkType())) { - SbkObjectType* shiboType = reinterpret_cast(SbkType()); - if (shiboType->ext_tocpp && isConvertible(pyobj)) { - T* cptr = reinterpret_cast(shiboType->ext_tocpp(pyobj)); + SbkBaseType* shiboType = reinterpret_cast(SbkType()); + if (BaseType::hasExternalCppConversions(shiboType) && isConvertible(pyobj)) { + T* cptr = reinterpret_cast(BaseType::callExternalCppConversion(shiboType, pyobj)); std::auto_ptr cptr_auto_ptr(cptr); return *cptr; } @@ -273,11 +271,9 @@ struct ObjectTypeConverter { if (pyobj == Py_None) return 0; - SbkObjectType* shiboType = reinterpret_cast(pyobj->ob_type); - if (shiboType->mi_specialcast) - return (T*) shiboType->mi_specialcast( - Wrapper::cppPointer(reinterpret_cast(pyobj), SbkType()), - reinterpret_cast(SbkType())); + SbkBaseType* shiboType = reinterpret_cast(pyobj->ob_type); + if (BaseType::hasCast(shiboType)) + return reinterpret_cast(BaseType::cast(shiboType, reinterpret_cast(pyobj), SbkType())); return (T*) Wrapper::cppPointer(reinterpret_cast(pyobj), SbkType()); } }; @@ -564,7 +560,7 @@ struct StdListConverter // binded types implementing sequence protocol, otherwise this will // cause a mess like QBitArray being accepted by someone expecting a // QStringList. - if ((SbkType() && isShibokenType(pyObj)) || !PySequence_Check(pyObj)) + if ((SbkType() && Wrapper::checkType(pyObj)) || !PySequence_Check(pyObj)) return false; for (int i = 0, max = PySequence_Length(pyObj); i < max; ++i) { AutoDecRef item(PySequence_GetItem(pyObj, i)); @@ -610,7 +606,7 @@ struct StdPairConverter { if (PyObject_TypeCheck(pyObj, SbkType())) return true; - if ((SbkType() && isShibokenType(pyObj)) || !PySequence_Check(pyObj) || PySequence_Length(pyObj) != 2) + if ((SbkType() && Wrapper::checkType(pyObj)) || !PySequence_Check(pyObj) || PySequence_Length(pyObj) != 2) return false; AutoDecRef item1(PySequence_GetItem(pyObj, 0)); @@ -655,7 +651,7 @@ struct StdMapConverter { if (PyObject_TypeCheck(pyObj, SbkType())) return true; - if ((SbkType() && isShibokenType(pyObj)) || !PyDict_Check(pyObj)) + if ((SbkType() && Wrapper::checkType(pyObj)) || !PyDict_Check(pyObj)) return false; PyObject* key; diff --git a/libshiboken/typeresolver.h b/libshiboken/typeresolver.h index bec99090..f959010f 100644 --- a/libshiboken/typeresolver.h +++ b/libshiboken/typeresolver.h @@ -26,8 +26,6 @@ #include "shibokenmacros.h" #include "conversions.h" -class SbkObjectType; - namespace Shiboken { From 1e4ec3e7f694bee931fd9d9af89dcaa405de1d2a Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Fri, 19 Nov 2010 17:01:22 -0300 Subject: [PATCH 135/564] Fix merge mistakes: * Replaces PySide::deleteDynamicQMetaObject by Shiboken::callCppDestructor * Shiboken namespace usage. --- generator/cppgenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 537c658f..284b20f8 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -794,7 +794,7 @@ void CppGenerator::writeMetaObjectMethod(QTextStream& s, const AbstractMetaClass Indentation indentation2(INDENT); s << INDENT << "m_metaObject = PySide::DynamicQMetaObject::createBasedOn((PyObject*)pySelf, pySelf->ob_type, &" << metaClass->qualifiedCppName() << "::staticMetaObject);" << endl - << INDENT << "Shiboken::Wrapper::setTypeUserData(pySelf, m_metaObject, PySide::deleteDynamicQMetaObject);" << endl; + << INDENT << "Shiboken::Wrapper::setTypeUserData(pySelf, m_metaObject, &Shiboken::callCppDestructor);" << endl; } s << INDENT << "} else {" << endl; { From fb6366565ee8a6718ca72589d0833498285ba048 Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Fri, 19 Nov 2010 18:47:41 -0300 Subject: [PATCH 136/564] Fixes SHIBOKEN_PYTHON_INCLUDE_DIR variable for cmake versions lesser than 2.8. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed by Luciano Wolf Reviewed by Renato Araújo --- CMakeLists.txt | 8 ++++++-- data/ShibokenConfig.cmake.in | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9fd6ff32..2f054633 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,8 +91,6 @@ if(APPLE) set(SBK_PYTHON_LIBRARIES "-undefined dynamic_lookup") endif() - - if (BUILD_TESTS) enable_testing() endif() @@ -110,6 +108,12 @@ if (QT4_FOUND AND ApiExtractor_FOUND AND GeneratorRunner_FOUND AND PYTHONLIBS_FO else() message("!! Some dependencies were not found, shiboken generator compilation disabled!") endif() + +if(CMAKE_VERSION VERSION_LESS 2.8) + set(SBK_PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_PATH}) +else() + set(SBK_PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_DIRS}) +endif() add_subdirectory(data) set(ARCHIVE_NAME ${CMAKE_PROJECT_NAME}-${shiboken_VERSION}) diff --git a/data/ShibokenConfig.cmake.in b/data/ShibokenConfig.cmake.in index bd39b39a..50d14c9f 100644 --- a/data/ShibokenConfig.cmake.in +++ b/data/ShibokenConfig.cmake.in @@ -12,7 +12,7 @@ elseif(WIN32) else() SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") endif() -SET(SHIBOKEN_PYTHON_INCLUDE_DIR "@PYTHON_INCLUDE_DIR@") +SET(SHIBOKEN_PYTHON_INCLUDE_DIR "@SBK_PYTHON_INCLUDE_DIR@") SET(SHIBOKEN_PYTHON_INTERPRETER "@PYTHON_EXECUTABLE@") SET(SHIBOKEN_PYTHON_LIBRARIES "@SBK_PYTHON_LIBRARIES@") SET(SHIBOKEN_BUILD_TYPE "@SHIBOKEN_BUILD_TYPE@") From 418a56668c8a587530e6bc2a2745b4e385cff5f6 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Tue, 23 Nov 2010 11:40:19 -0300 Subject: [PATCH 137/564] Created debug function on samle bindings. This function 'cacheSize()' can be used to check how many objects still registered on BindingManager. Reviewer: Luciano Wolf Hugo Parente Lima --- tests/samplebinding/protected_test.py | 29 +++++++++++++++++++---- tests/samplebinding/typesystem_sample.xml | 5 ++++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/tests/samplebinding/protected_test.py b/tests/samplebinding/protected_test.py index 88ac5b59..e9d8b81e 100644 --- a/tests/samplebinding/protected_test.py +++ b/tests/samplebinding/protected_test.py @@ -27,7 +27,9 @@ '''Test cases for protected methods.''' import unittest +import sys +from sample import cacheSize from sample import ProtectedNonPolymorphic, ProtectedVirtualDestructor from sample import ProtectedPolymorphic, ProtectedPolymorphicDaughter, ProtectedPolymorphicGrandDaughter from sample import ProtectedProperty, ProtectedEnumClass @@ -68,6 +70,9 @@ def __init__(self): class ProtectedNonPolymorphicTest(unittest.TestCase): '''Test cases for protected method in a class without virtual methods.''' + def tearDown(self): + self.assertEqual(cacheSize(), 0) + def testProtectedCall(self): '''Calls a non-virtual protected method.''' p = ProtectedNonPolymorphic('NonPoly') @@ -92,6 +97,9 @@ def testModifiedProtectedCall(self): class ProtectedPolymorphicTest(unittest.TestCase): '''Test cases for protected method in a class with virtual methods.''' + def tearDown(self): + self.assertEqual(cacheSize(), 0) + def testProtectedCall(self): '''Calls a virtual protected method.''' p = ProtectedNonPolymorphic('Poly') @@ -113,7 +121,6 @@ def testReimplementedProtectedCall(self): self.assert_(p.protectedName_called) self.assertEqual(p.protectedName(), name) self.assertEqual(ProtectedPolymorphic.protectedName(p), original_name) - class ProtectedPolymorphicDaugherTest(unittest.TestCase): '''Test cases for protected method in a class inheriting for a class with virtual methods.''' @@ -128,15 +135,18 @@ def testReimplementedProtectedCall(self): original_name = 'Poly' p = ExtendedProtectedPolymorphicDaughter(original_name) name = p.callProtectedName() - print "MyName:", name self.assert_(p.protectedName_called) self.assertEqual(p.protectedName(), name) self.assertEqual(ProtectedPolymorphicDaughter.protectedName(p), original_name) + class ProtectedPolymorphicGrandDaugherTest(unittest.TestCase): '''Test cases for protected method in a class inheriting for a class that inherits from another with protected virtual methods.''' + def tearDown(self): + self.assertEqual(cacheSize(), 0) + def testProtectedCallWithInstanceCreatedOnCpp(self): '''Calls a virtual protected method from parent class on an instance created in C++.''' p = ProtectedPolymorphicGrandDaughter.create() @@ -158,6 +168,9 @@ class ProtectedVirtualDtorTest(unittest.TestCase): def setUp(self): ProtectedVirtualDestructor.resetDtorCounter() + def tearDown(self): + self.assertEqual(cacheSize(), 0) + def testVirtualProtectedDtor(self): '''Original protected virtual destructor is being called.''' dtor_called = ProtectedVirtualDestructor.dtorCalled() @@ -198,6 +211,9 @@ def publicEnumMethod(self, value): class ProtectedEnumTest(unittest.TestCase): '''Test cases for protected enum.''' + def tearDown(self): + self.assertEqual(cacheSize(), 0) + def testProtectedMethodWithProtectedEnumArgument(self): '''Calls protected method with protected enum argument.''' obj = ProtectedEnumClass() @@ -250,6 +266,9 @@ def testOverriddenProtectedMethodWithPublicEnumArgument(self): class ProtectedPropertyTest(unittest.TestCase): '''Test cases for a class with a protected property (or field in C++).''' + def tearDown(self): + self.assertEqual(cacheSize(), 0) + def testProtectedProperty(self): '''Writes and reads a protected property.''' obj = ProtectedProperty() @@ -257,10 +276,12 @@ def testProtectedProperty(self): obj.protectedProperty = 3 self.assertEqual(obj.protectedProperty, 3) - class PrivateDtorProtectedMethodTest(unittest.TestCase): '''Test cases for classes with private destructors and protected methods.''' + def tearDown(self): + self.assertEqual(cacheSize(), 0) + def testProtectedMethod(self): '''Calls protected method of a class with a private destructor.''' obj = PrivateDtor.instance() @@ -268,12 +289,10 @@ def testProtectedMethod(self): self.assertEqual(type(obj), PrivateDtor) self.assertEqual(obj.instanceCalls(), 1) self.assertEqual(obj.instanceCalls(), obj.protectedInstanceCalls()) - obj = PrivateDtor.instance() self.assertEqual(obj.instanceCalls(), 2) self.assertEqual(obj.instanceCalls(), obj.protectedInstanceCalls()) - if __name__ == '__main__': unittest.main() diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 37fa4742..b0fff8dc 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -45,6 +45,11 @@ + + + %PYARG_0 = %CONVERTTOPYTHON[int](Shiboken::BindingManager::instance().getAllPyObjects().size()); + + From 81a8bd714bf4ea7783277052da932d8a7a909fd1 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Tue, 23 Nov 2010 11:42:08 -0300 Subject: [PATCH 138/564] Fixed generation with AVOID_PROTECTED_HACK. Fixes bug #476. Reviewer: Luciano Wolf Hugo Parente Lima --- generator/cppgenerator.cpp | 66 +++++++++++++++++++++++-------------- libshiboken/basewrapper.cpp | 9 +++-- libshiboken/basewrapper_p.h | 2 +- 3 files changed, 47 insertions(+), 30 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 284b20f8..b1f8d573 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2010,27 +2010,35 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f mc << ')'; } else { if (func->ownerClass()) { -#ifndef AVOID_PROTECTED_HACK - if (func->isStatic()) - mc << func->ownerClass()->qualifiedCppName() << "::"; - else - mc << CPP_SELF_VAR "->"; +#ifdef AVOID_PROTECTED_HACK + if (!func->isProtected()) { +#endif + if (func->isStatic()) + mc << func->ownerClass()->qualifiedCppName() << "::"; + else { +#ifdef AVOID_PROTECTED_HACK + if (!func->isVirtual() && func->ownerClass()->hasProtectedMembers()) + mc << "((" << func->ownerClass()->qualifiedCppName() << "*)" << CPP_SELF_VAR << ")->"; + else +#endif + mc << CPP_SELF_VAR "->"; + } - if (!func->isAbstract() && func->isVirtual()) - mc << "::%CLASS_NAME::"; + if (!func->isAbstract() && func->isVirtual()) + mc << "::%CLASS_NAME::"; - mc << func->originalName(); -#else - if (func->isStatic()) - mc << func->ownerClass()->qualifiedCppName() << "::"; - else { - if (func->isProtected()) - mc << "((" << wrapperName(func->ownerClass()) << "*) "; - mc << CPP_SELF_VAR << (func->isProtected() ? ")" : "") << "->"; + + mc << func->originalName(); + +#ifdef AVOID_PROTECTED_HACK + } else { + if (!func->isStatic()) + mc << "((" << wrapperName(func->ownerClass()) << "*) " << CPP_SELF_VAR << ")->"; + + if (!func->isAbstract()) + mc << (func->isProtected() ? wrapperName(func->ownerClass()) : "::" + func->ownerClass()->qualifiedCppName()) << "::"; + mc << func->originalName() << "_protected"; } - if (!func->isAbstract() && func->isVirtual()) - mc << (func->isProtected() ? wrapperName(func->ownerClass()) : "::%CLASS_NAME::"); - mc << func->originalName() << (func->isProtected() ? "_protected" : ""); #endif } else { mc << func->originalName(); @@ -2038,13 +2046,19 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f mc << '(' << userArgs.join(", ") << ')'; if (!func->isAbstract() && func->isVirtual()) { mc.flush(); - QString virtualCall(methodCall); - QString normalCall(methodCall); +#ifndef AVOID_PROTECTED_HACK + if (!func->isProtected()) +#endif + { + QString virtualCall(methodCall); + QString normalCall(methodCall); + + virtualCall = virtualCall.replace("%CLASS_NAME", func->ownerClass()->qualifiedCppName()); + normalCall = normalCall.replace("::%CLASS_NAME::", ""); + methodCall = ""; - virtualCall = virtualCall.replace("%CLASS_NAME", func->ownerClass()->qualifiedCppName()); - normalCall = normalCall.replace("::%CLASS_NAME::", ""); - methodCall = ""; - mc << "(Shiboken::Wrapper::isUserType(self) ? " << virtualCall << ":" << normalCall << ")"; + mc << "(Shiboken::Wrapper::isUserType(self) ? " << virtualCall << ":" << normalCall << ")"; + } } } } @@ -3247,6 +3261,10 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m if (metaClass->hasProtectedDestructor()) dtorClassName = wrapperName(metaClass); #endif + // call the real destructor + if (metaClass->typeEntry()->isValue()) + dtorClassName = wrapperName(metaClass); + s << INDENT << "Shiboken::BaseType::setDestructorFunction(&" << cpythonTypeName(metaClass) << ", &Shiboken::callCppDestructor<" << dtorClassName << " >);" << endl; } diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 39c18c3e..6fb69bf9 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -170,7 +170,7 @@ void SbkDeallocWrapper(PyObject* pyObj) } } - Shiboken::Wrapper::deallocData(sbkObj); + Shiboken::Wrapper::deallocData(sbkObj, !sbkObj->d->containsCppWrapper); } void SbkDeallocWrapperWithPrivateDtor(PyObject* self) @@ -179,8 +179,7 @@ void SbkDeallocWrapperWithPrivateDtor(PyObject* self) if (sbkObj->weakreflist) PyObject_ClearWeakRefs(self); - Shiboken::BindingManager::instance().releaseWrapper(sbkObj); - Shiboken::Wrapper::deallocData(sbkObj); + Shiboken::Wrapper::deallocData(sbkObj, true); } void SbkBaseTypeDealloc(PyObject* pyObj) @@ -927,10 +926,10 @@ void setParent(PyObject* parent, PyObject* child) Py_DECREF(child); } -void deallocData(SbkObject* self) +void deallocData(SbkObject* self, bool cleanup) { // Make cleanup if this is not a wrapper otherwise this will be done on wrapper destructor - if(!self->d->containsCppWrapper) { + if(cleanup) { removeParent(self); if (self->d->parentInfo) diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h index 702fdbd0..428159e0 100644 --- a/libshiboken/basewrapper_p.h +++ b/libshiboken/basewrapper_p.h @@ -229,7 +229,7 @@ void clearReferences(SbkObject* self); /** * Destroy internal data **/ -void deallocData(SbkObject* self); +void deallocData(SbkObject* self, bool doCleanup); } // namespace Wrapper } // namespace Shiboken From ea46607ca87ce2233529c8177ab51424337613d2 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 19 Nov 2010 17:56:10 -0200 Subject: [PATCH 139/564] namespace Shiboken::BaseType renamed to Shiboken::ObjectType. --- generator/cppgenerator.cpp | 58 +++++++++++------------ generator/headergenerator.cpp | 44 +++++++++-------- generator/shibokengenerator.cpp | 10 ++-- libshiboken/basewrapper.cpp | 10 ++-- libshiboken/basewrapper.h | 2 +- libshiboken/conversions.h | 12 ++--- tests/samplebinding/typesystem_sample.xml | 12 ++--- 7 files changed, 76 insertions(+), 72 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index d1ebf773..fe90843f 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -209,8 +209,6 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl if (metaClass->typeEntry()->typeFlags() & ComplexTypeEntry::Deprecated) s << "#Deprecated" << endl; - s << "using namespace Shiboken;" << endl; - //Use class base namespace const AbstractMetaClass *context = metaClass->enclosingClass(); while(context) { @@ -470,8 +468,8 @@ void CppGenerator::writeDestructorNative(QTextStream &s, const AbstractMetaClass { Indentation indentation(INDENT); s << wrapperName(metaClass) << "::~" << wrapperName(metaClass) << "()" << endl << '{' << endl; - s << INDENT << "SbkObject* wrapper = BindingManager::instance().retrieveWrapper(this);" << endl; - s << INDENT << "Wrapper::destroy(wrapper);" << endl; + s << INDENT << "SbkObject* wrapper = Shiboken::BindingManager::instance().retrieveWrapper(this);" << endl; + s << INDENT << "Shiboken::Wrapper::destroy(wrapper);" << endl; s << '}' << endl; } @@ -534,7 +532,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu s << INDENT << "Shiboken::GilState gil;" << endl; - s << INDENT << "Shiboken::AutoDecRef py_override(BindingManager::instance().getOverride(this, \""; + s << INDENT << "Shiboken::AutoDecRef py_override(Shiboken::BindingManager::instance().getOverride(this, \""; s << func->name() << "\"));" << endl; s << INDENT << "if (py_override.isNull()) {" << endl; @@ -682,7 +680,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu if (func->type()->isPrimitive()) desiredType = "\"" + func->type()->name() + "\""; else - desiredType = "SbkType<" + typeName + " >()->tp_name"; + desiredType = "Shiboken::SbkType<" + typeName + " >()->tp_name"; } } else { s << guessCPythonIsConvertible(func->typeReplaced(0)); @@ -740,7 +738,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu if (invalidateReturn) { s << INDENT << "if (invalidadeArg0)" << endl; Indentation indentation(INDENT); - s << INDENT << "Wrapper::invalidate(" << PYTHON_RETURN_VAR ".object());" << endl; + s << INDENT << "Shiboken::Wrapper::invalidate(" << PYTHON_RETURN_VAR ".object());" << endl; } foreach (FunctionModification funcMod, func->modifications()) { @@ -748,7 +746,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu if (argMod.resetAfterUse) { s << INDENT << "if (invalidadeArg" << argMod.index << ")" << endl; Indentation indentation(INDENT); - s << INDENT << "Wrapper::invalidate(PyTuple_GET_ITEM(pyargs, "; + s << INDENT << "Shiboken::Wrapper::invalidate(PyTuple_GET_ITEM(pyargs, "; s << (argMod.index - 1) << "));" << endl; } } @@ -787,14 +785,14 @@ void CppGenerator::writeMetaObjectMethod(QTextStream& s, const AbstractMetaClass s << INDENT << "if (!m_metaObject) {\n"; { Indentation indentation(INDENT); - s << INDENT << "SbkObject* pySelf = BindingManager::instance().retrieveWrapper(this);\n" + s << INDENT << "SbkObject* pySelf = Shiboken::BindingManager::instance().retrieveWrapper(this);\n" << INDENT << "void* typeData = Shiboken::Wrapper::getTypeUserData(pySelf);" << endl << INDENT << "if (!typeData) {" << endl; { Indentation indentation2(INDENT); s << INDENT << "m_metaObject = PySide::DynamicQMetaObject::createBasedOn((PyObject*)pySelf, pySelf->ob_type, &" << metaClass->qualifiedCppName() << "::staticMetaObject);" << endl - << INDENT << "Shiboken::Wrapper::setTypeUserData(pySelf, m_metaObject, PySide::deleteDynamicQMetaObject);" << endl; + << INDENT << "Shiboken::Object::setTypeUserData(pySelf, m_metaObject, Shiboken::callCppDestructor);" << endl; } s << INDENT << "} else {" << endl; { @@ -830,7 +828,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun // Check if the right constructor was called. if (!metaClass->hasPrivateDestructor()) { - s << INDENT << "if (Shiboken::Wrapper::isUserType(self) && !Shiboken::BaseType::canCallConstructor(self->ob_type, Shiboken::SbkType<" << metaClass->qualifiedCppName() << " >()))" << endl; + s << INDENT << "if (Shiboken::Wrapper::isUserType(self) && !Shiboken::ObjectType::canCallConstructor(self->ob_type, Shiboken::SbkType<" << metaClass->qualifiedCppName() << " >()))" << endl; Indentation indent(INDENT); s << INDENT << "return " << m_currentErrorCode << ';' << endl << endl; } @@ -891,7 +889,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun } { Indentation indentation(INDENT); - s << INDENT << "Shiboken::BaseType::copyMultimpleheritance(type, myType);" << endl; + s << INDENT << "Shiboken::ObjectType::copyMultimpleheritance(type, myType);" << endl; } if (!metaClass->isAbstract()) s << INDENT << '}' << endl << endl; @@ -941,7 +939,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun // Python owns it and C++ wrapper is false. if (shouldGenerateCppWrapper(overloads.first()->ownerClass())) s << INDENT << "Shiboken::Wrapper::setHasCppWrapper(sbkSelf, true);" << endl; - s << INDENT << "BindingManager::instance().registerWrapper(sbkSelf, cptr);" << endl; + s << INDENT << "Shiboken::BindingManager::instance().registerWrapper(sbkSelf, cptr);" << endl; // Create metaObject and register signal/slot if (metaClass->isQObject() && usePySideExtensions()) { @@ -2128,15 +2126,15 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f s << INDENT; if (arg_mod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::TargetLangOwnership) { - s << "Wrapper::getOwnership(" << pyArgName << ");"; + s << "Shiboken::Wrapper::getOwnership(" << pyArgName << ");"; } else if (wrappedClass->hasVirtualDestructor()) { if (arg_mod.index == 0) { - s << "Wrapper::releaseOwnership(" PYTHON_RETURN_VAR ");"; + s << "Shiboken::Wrapper::releaseOwnership(" PYTHON_RETURN_VAR ");"; } else { - s << "Wrapper::releaseOwnership(" << pyArgName << ");"; + s << "Shiboken::Wrapper::releaseOwnership(" << pyArgName << ");"; } } else { - s << "Wrapper::invalidate(" << pyArgName << ");"; + s << "Shiboken::Wrapper::invalidate(" << pyArgName << ");"; } s << endl; } @@ -2284,8 +2282,8 @@ void CppGenerator::writeExtendedConverterInitialization(QTextStream& s, const Ty s << INDENT << "shiboType = reinterpret_cast("; s << cppApiVariableName(externalType->targetLangPackage()) << '['; s << getTypeIndexVariableName(externalType) << "]);" << endl; - s << INDENT << "Shiboken::BaseType::setExternalIsConvertibleFunction(shiboType, " << extendedIsConvertibleFunctionName(externalType) << ");" << endl; - s << INDENT << "Shiboken::BaseType::setExternalCppConversionFunction(shiboType, " << extendedToCppFunctionName(externalType) << ");" << endl; + s << INDENT << "Shiboken::ObjectType::setExternalIsConvertibleFunction(shiboType, " << extendedIsConvertibleFunctionName(externalType) << ");" << endl; + s << INDENT << "Shiboken::ObjectType::setExternalCppConversionFunction(shiboType, " << extendedToCppFunctionName(externalType) << ");" << endl; } QString CppGenerator::multipleInheritanceInitializerFunctionName(const AbstractMetaClass* metaClass) @@ -3202,7 +3200,7 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m s << INDENT << cpythonTypeNameExt(metaClass->typeEntry()) << " = reinterpret_cast(&" << cpythonTypeName(metaClass->typeEntry()) << ");" << endl << endl; // alloc private data - s << INDENT << "Shiboken::BaseType::initPrivateData(&" << cpythonTypeName(metaClass->typeEntry()) << ");" << endl; + s << INDENT << "Shiboken::ObjectType::initPrivateData(&" << cpythonTypeName(metaClass->typeEntry()) << ");" << endl; // class inject-code target/beginning if (!metaClass->typeEntry()->codeSnips().isEmpty()) { @@ -3234,10 +3232,10 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m if (miClass == metaClass) s << INDENT << "func = " << multipleInheritanceInitializerFunctionName(miClass) << ";" << endl; else - s << INDENT << "func = Shiboken::BaseType::getMultipleIheritanceFunction(reinterpret_cast(" << cpythonTypeNameExt(miClass->typeEntry()) << "));" << endl; + s << INDENT << "func = Shiboken::ObjectType::getMultipleIheritanceFunction(reinterpret_cast(" << cpythonTypeNameExt(miClass->typeEntry()) << "));" << endl; - s << INDENT << "Shiboken::BaseType::setMultipleIheritanceFunction(&" << cpythonTypeName(metaClass) << ", func);" << endl; - s << INDENT << "Shiboken::BaseType::setCastFunction(&" << cpythonTypeName(metaClass) << ", &" << cpythonSpecialCastFunctionName(metaClass) << ");" << endl; + s << INDENT << "Shiboken::ObjectType::setMultipleIheritanceFunction(&" << cpythonTypeName(metaClass) << ", func);" << endl; + s << INDENT << "Shiboken::ObjectType::setCastFunction(&" << cpythonTypeName(metaClass) << ", &" << cpythonSpecialCastFunctionName(metaClass) << ");" << endl; } // Fill destrutor @@ -3247,12 +3245,12 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m if (metaClass->hasProtectedDestructor()) dtorClassName = wrapperName(metaClass); #endif - s << INDENT << "Shiboken::BaseType::setDestructorFunction(&" << cpythonTypeName(metaClass) << ", &Shiboken::callCppDestructor<" << dtorClassName << " >);" << endl; + s << INDENT << "Shiboken::ObjectType::setDestructorFunction(&" << cpythonTypeName(metaClass) << ", &Shiboken::callCppDestructor<" << dtorClassName << " >);" << endl; } // Fill copy function if (metaClass->typeEntry()->isValue() && shouldGenerateCppWrapper(metaClass)) - s << INDENT << "Shiboken::BaseType::setCopyFunction(&" << cpythonTypeName(metaClass) << ", &" << cpythonBaseName(metaClass) + "_ObjCopierFunc);" << endl; + s << INDENT << "Shiboken::ObjectType::setCopyFunction(&" << cpythonTypeName(metaClass) << ", &" << cpythonBaseName(metaClass) + "_ObjCopierFunc);" << endl; s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << pyTypeName << ") < 0)" << endl; s << INDENT << INDENT << "return;" << endl << endl; @@ -3261,7 +3259,7 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m if (metaClass->isPolymorphic()) { s << INDENT << "// Fill type discovery information" << endl; if (metaClass->baseClass()) { - s << INDENT << "Shiboken::BaseType::setTypeDiscoveryFunction(&" << cpythonTypeName(metaClass) << ", &" << cpythonBaseName(metaClass) << "_typeDiscovery);" << endl; + s << INDENT << "Shiboken::ObjectType::setTypeDiscoveryFunction(&" << cpythonTypeName(metaClass) << ", &" << cpythonBaseName(metaClass) << "_typeDiscovery);" << endl; s << INDENT << "Shiboken::BindingManager& bm = Shiboken::BindingManager::instance();" << endl; foreach (const AbstractMetaClass* base, baseClasses) { s << INDENT << "bm.addClassInheritance(reinterpret_cast(" << cpythonTypeNameExt(base->typeEntry()) << "), &" << cpythonTypeName(metaClass) << ");" << endl; @@ -3274,7 +3272,7 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m QByteArray suffix; if (metaClass->typeEntry()->isObject() || metaClass->typeEntry()->isQObject()) suffix = "*"; - s << INDENT << "Shiboken::BaseType::setOriginalName(&" << pyTypeName << ", \"" << metaClass->qualifiedCppName() << suffix << "\");" << endl; + s << INDENT << "Shiboken::ObjectType::setOriginalName(&" << pyTypeName << ", \"" << metaClass->qualifiedCppName() << suffix << "\");" << endl; if (metaClass->enclosingClass() && (metaClass->enclosingClass()->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass) ) { s << INDENT << "PyDict_SetItemString(module," @@ -3460,7 +3458,7 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, const AbstractMetaClass s << INDENT << "if (!attr && !QString(PyString_AS_STRING(name)).startsWith(\"__\")) {" << endl; { Indentation indent(INDENT); - s << INDENT << "QObject* cppSelf = Converter::toCpp(self);" << endl + s << INDENT << "QObject* cppSelf = Shiboken::Converter::toCpp(self);" << endl << INDENT << "const QMetaObject* metaObject = cppSelf->metaObject();" << endl << INDENT << "QByteArray cname(PyString_AS_STRING(name));" << endl << INDENT << "cname += '(';" << endl @@ -3807,7 +3805,7 @@ bool CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMeta else childVariable = usePyArgs ? "pyargs["+QString::number(childIndex-1)+"]" : "arg"; - s << INDENT << "Wrapper::setParent(" << parentVariable << ", " << childVariable << ");\n"; + s << INDENT << "Shiboken::Wrapper::setParent(" << parentVariable << ", " << childVariable << ");\n"; return true; } @@ -3841,7 +3839,7 @@ void CppGenerator::writeReturnValueHeuristics(QTextStream& s, const AbstractMeta } if (type->isQObject() || type->isObject() || type->isValuePointer()) - s << INDENT << "Wrapper::setParent(" << self << ", " PYTHON_RETURN_VAR ");" << endl; + s << INDENT << "Shiboken::Wrapper::setParent(" << self << ", " PYTHON_RETURN_VAR ");" << endl; } void CppGenerator::writeHashFunction(QTextStream& s, const AbstractMetaClass* metaClass) diff --git a/generator/headergenerator.cpp b/generator/headergenerator.cpp index f1b8086d..3f14712b 100644 --- a/generator/headergenerator.cpp +++ b/generator/headergenerator.cpp @@ -214,8 +214,8 @@ void HeaderGenerator::writeTypeConverterDecl(QTextStream& s, const TypeEntry* ty } bool isValueTypeWithImplConversions = type->isValue() && !implicitConvs.isEmpty(); bool hasCustomConversion = type->hasNativeConversionRule(); - QString typeT = type->name() + (isAbstractOrObjectType ? "*" : ""); - QString typeName = type->name(); + QString typeT = "::" + type->qualifiedCppName() + (isAbstractOrObjectType ? "*" : ""); + QString typeName = "::" + type->qualifiedCppName(); #ifdef AVOID_PROTECTED_HACK const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(type); @@ -225,7 +225,7 @@ void HeaderGenerator::writeTypeConverterDecl(QTextStream& s, const TypeEntry* ty } #endif - s << "struct Converter<" << typeT << " >"; + s << "struct Converter< " << typeT << " >"; if (!hasCustomConversion) { if (type->isEnum()) s << " : EnumConverter"; @@ -235,17 +235,17 @@ void HeaderGenerator::writeTypeConverterDecl(QTextStream& s, const TypeEntry* ty s << " : ObjectTypeConverter"; else s << " : ValueTypeConverter"; - s << '<' << typeName << " >"; + s << "< " << typeName << " >"; } s << endl << '{' << endl; if (isValueTypeWithImplConversions || hasCustomConversion) { - s << INDENT << "static " << type->name() << " toCpp(PyObject* pyobj);" << endl; + s << INDENT << "static " << typeName << " toCpp(PyObject* pyobj);" << endl; s << INDENT << "static bool isConvertible(PyObject* pyobj);" << endl; if (hasCustomConversion) { s << INDENT << "static bool checkType(PyObject* pyobj);" << endl; - s << INDENT << "static inline PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast<" - << type->name() << (isAbstractOrObjectType ? "" : "*") << " >(cppObj)); }" << endl; - s << INDENT << "static PyObject* toPython(const " << type->name() << "& cppObj);" << endl; + s << INDENT << "static inline PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast< " + << typeName << (isAbstractOrObjectType ? "" : "*") << " >(cppObj)); }" << endl; + s << INDENT << "static PyObject* toPython(const " << typeName << "& cppObj);" << endl; } } s << "};" << endl; @@ -253,7 +253,7 @@ void HeaderGenerator::writeTypeConverterDecl(QTextStream& s, const TypeEntry* ty // write value-type like converter to object-types if (isAbstractOrObjectType) { s << endl << "template<>" << endl; - s << "struct Converter<" << type->name() << "& > : ObjectTypeReferenceConverter<" << type->name() << " >" << endl << '{' << endl; + s << "struct Converter< " << typeName << " > : ObjectTypeReferenceConverter< " << typeName << " >" << endl << '{' << endl; s << "};" << endl; } } @@ -434,7 +434,7 @@ void HeaderGenerator::finishGeneration() s << INDENT << metaClass->qualifiedCppName() << "* value = const_cast<" << metaClass->qualifiedCppName() << "* >(cppobj);" << endl; s << INDENT << "if (!isExactType)" << endl; s << INDENT << INDENT << "typeName = typeid(*value).name();" << endl; - s << INDENT << "PyObject* pyObj = Shiboken::Wrapper::newObject(reinterpret_cast(SbkType<" << metaClass->qualifiedCppName() << " >())," + s << INDENT << "PyObject* pyObj = Shiboken::Wrapper::newObject(reinterpret_cast(SbkType< ::" << metaClass->qualifiedCppName() << " >())," << "value, hasOwnership, isExactType, typeName);" << endl; s << INDENT << "PySide::Signal::updateSourceObject(pyObj);" << endl; s << INDENT << "return pyObj;" << endl; @@ -472,19 +472,19 @@ void HeaderGenerator::writeSbkTypeFunction(QTextStream& s, const AbstractMetaEnu } #endif - s << "template<> inline PyTypeObject* SbkType<" << enumName << " >() "; + s << "template<> inline PyTypeObject* SbkType< ::" << enumName << " >() "; s << "{ return " << cpythonTypeNameExt(cppEnum->typeEntry()) << "; }\n"; FlagsTypeEntry* flag = cppEnum->typeEntry()->flags(); if (flag) { - s << "template<> inline PyTypeObject* SbkType<" << flag->name() << " >() " + s << "template<> inline PyTypeObject* SbkType< ::" << flag->name() << " >() " << "{ return " << cpythonTypeNameExt(flag) << "; }\n"; } } void HeaderGenerator::writeSbkTypeFunction(QTextStream& s, const AbstractMetaClass* cppClass) { - s << "template<> inline PyTypeObject* SbkType<" << cppClass->qualifiedCppName() << " >() " + s << "template<> inline PyTypeObject* SbkType< ::" << cppClass->qualifiedCppName() << " >() " << "{ return reinterpret_cast(" << cpythonTypeNameExt(cppClass->typeEntry()) << "); }\n"; } @@ -520,19 +520,21 @@ void HeaderGenerator::writeTypeConverterImpl(QTextStream& s, const TypeEntry* ty if (!hasImplicitConversions) return; + const QString typeName = "::" + type->qualifiedCppName(); + // Write Converter::isConvertible - s << "inline bool Shiboken::Converter<" << type->name() << " >::isConvertible(PyObject* pyobj)" << endl; + s << "inline bool Shiboken::Converter< " << typeName << " >::isConvertible(PyObject* pyobj)" << endl; s << '{' << endl; if (type->isValue()) { - s << INDENT << "if (ValueTypeConverter<" << type->name() << " >::isConvertible(pyobj))" << endl; + s << INDENT << "if (ValueTypeConverter< " << typeName << " >::isConvertible(pyobj))" << endl; Indentation indent(INDENT); s << INDENT << "return true;" << endl; } - s << INDENT << "SbkObjectType* shiboType = reinterpret_cast(SbkType<"; - s << type->name() << " >());" << endl; + s << INDENT << "SbkObjectType* shiboType = reinterpret_cast(SbkType< "; + s << typeName << " >());" << endl; s << INDENT << "return "; bool isFirst = true; foreach (const AbstractMetaFunction* ctor, implicitConvs) { @@ -550,15 +552,15 @@ void HeaderGenerator::writeTypeConverterImpl(QTextStream& s, const TypeEntry* ty s << endl; { Indentation indent(INDENT); - s << INDENT << " || (BaseType::isExternalConvertible(shiboType, pyobj));" << endl; + s << INDENT << " || (ObjectType::isExternalConvertible(shiboType, pyobj));" << endl; } s << '}' << endl << endl; // Write Converter::toCpp function - s << "inline " << type->name() << " Shiboken::Converter<" << type->name() << " >::toCpp(PyObject* pyobj)" << endl; + s << "inline " << typeName << " Shiboken::Converter< " << typeName << " >::toCpp(PyObject* pyobj)" << endl; s << '{' << endl; - s << INDENT << "if (PyObject_TypeCheck(pyobj, SbkType<" << type->qualifiedCppName() << ">()))" << endl; + s << INDENT << "if (PyObject_TypeCheck(pyobj, SbkType< " << typeName << " >()))" << endl; { Indentation indent(INDENT); s << INDENT << "return *" << cpythonWrapperCPtr(type, "pyobj") << ';' << endl; @@ -594,7 +596,7 @@ void HeaderGenerator::writeTypeConverterImpl(QTextStream& s, const TypeEntry* ty s << INDENT << "else" << endl; { Indentation indent(INDENT); - s << INDENT << "return Shiboken::ValueTypeConverter<" << type->qualifiedCppName() << " >::toCpp(pyobj);" << endl; + s << INDENT << "return Shiboken::ValueTypeConverter< " << typeName << " >::toCpp(pyobj);" << endl; } } s << '}' << endl << endl; diff --git a/generator/shibokengenerator.cpp b/generator/shibokengenerator.cpp index 4990eb19..5ddbb6d7 100644 --- a/generator/shibokengenerator.cpp +++ b/generator/shibokengenerator.cpp @@ -471,12 +471,14 @@ QString ShibokenGenerator::getFunctionReturnType(const AbstractMetaFunction* fun static QString baseConversionString(QString typeName) { - return QString("Shiboken::Converter<%1 >::").arg(typeName); + return QString("Shiboken::Converter< %1 >::").arg(typeName); } void ShibokenGenerator::writeBaseConversion(QTextStream& s, const TypeEntry* type) { - QString typeName = type->name(); + QString typeName = type->qualifiedCppName(); + if (!type->isCppPrimitive()) + typeName.prepend("::"); if (type->isObject()) typeName.append('*'); #ifdef AVOID_PROTECTED_HACK @@ -501,9 +503,11 @@ void ShibokenGenerator::writeBaseConversion(QTextStream& s, const AbstractMetaTy } else { if (type->isObject() || (type->isValue() && !type->isReference())) options |= Generator::ExcludeConst; - if (type->isContainer() ) + if (type->isContainer() || (type->isConstant() && type->isReference())) options |= Generator::ExcludeReference | Generator::ExcludeConst; typeName = translateTypeForWrapperMethod(type, context, options); + if (!type->typeEntry()->isCppPrimitive()) + typeName.prepend("::"); } s << baseConversionString(typeName); diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 5c47a357..948a24e3 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -437,7 +437,7 @@ static void decRefPyObjectList(const std::list& lst) } } -namespace BaseType +namespace ObjectType { bool checkType(PyTypeObject* type) @@ -447,7 +447,7 @@ bool checkType(PyTypeObject* type) bool isUserType(PyTypeObject* type) { - return BaseType::checkType(type) && reinterpret_cast(type)->d->is_user_type; + return checkType(type) && reinterpret_cast(type)->d->is_user_type; } bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType) @@ -561,19 +561,19 @@ void initPrivateData(SbkObjectType* self) memset(self->d, 0, sizeof(SbkBaseTypePrivate)); } -} // namespace BaseType +} // namespace ObjectType namespace Wrapper { bool checkType(PyObject* pyObj) { - return BaseType::checkType(pyObj->ob_type); + return ObjectType::checkType(pyObj->ob_type); } bool isUserType(PyObject* pyObj) { - return BaseType::isUserType(pyObj->ob_type); + return ObjectType::isUserType(pyObj->ob_type); } static void setSequenceOwnership(PyObject* pyObj, bool owner) diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 80207e25..7ae5502f 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -108,7 +108,7 @@ void callCppDestructor(void* cptr) LIBSHIBOKEN_API bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr); LIBSHIBOKEN_API void setErrorAboutWrongArguments(PyObject* args, const char* funcName, const char** cppOverloads); -namespace BaseType { +namespace ObjectType { /** * Returns true if the object is an instance of a type created by the Shiboken generator. diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index afc4989f..5d0048fe 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -99,7 +99,7 @@ struct CppObjectCopier { static inline T* copy(const T& obj) { - return reinterpret_cast(BaseType::copy(reinterpret_cast(SbkType()), &obj)); + return reinterpret_cast(ObjectType::copy(reinterpret_cast(SbkType()), &obj)); } }; @@ -214,7 +214,7 @@ struct ValueTypeConverter if (PyObject_TypeCheck(pyobj, SbkType())) return true; SbkObjectType* shiboType = reinterpret_cast(SbkType()); - return BaseType::isExternalConvertible(shiboType, pyobj); + return ObjectType::isExternalConvertible(shiboType, pyobj); } static inline PyObject* toPython(void* cppobj) { return toPython(*reinterpret_cast(cppobj)); } static inline PyObject* toPython(const T& cppobj) @@ -232,8 +232,8 @@ struct ValueTypeConverter { if (!PyObject_TypeCheck(pyobj, SbkType())) { SbkObjectType* shiboType = reinterpret_cast(SbkType()); - if (BaseType::hasExternalCppConversions(shiboType) && isConvertible(pyobj)) { - T* cptr = reinterpret_cast(BaseType::callExternalCppConversion(shiboType, pyobj)); + if (ObjectType::hasExternalCppConversions(shiboType) && isConvertible(pyobj)) { + T* cptr = reinterpret_cast(ObjectType::callExternalCppConversion(shiboType, pyobj)); std::auto_ptr cptr_auto_ptr(cptr); return *cptr; } @@ -272,8 +272,8 @@ struct ObjectTypeConverter if (pyobj == Py_None) return 0; SbkObjectType* shiboType = reinterpret_cast(pyobj->ob_type); - if (BaseType::hasCast(shiboType)) - return reinterpret_cast(BaseType::cast(shiboType, reinterpret_cast(pyobj), SbkType())); + if (ObjectType::hasCast(shiboType)) + return reinterpret_cast(ObjectType::cast(shiboType, reinterpret_cast(pyobj), SbkType())); return (T*) Wrapper::cppPointer(reinterpret_cast(pyobj), SbkType()); } }; diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 37fa4742..fb46eb2f 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -178,9 +178,9 @@ if ((*it)->isLayoutType()) { ObjectTypeLayout* l = reinterpret_cast<ObjectTypeLayout*>(*it); reparent_layout_items(parent, %CONVERTTOPYTHON[ObjectTypeLayout*](l)); - Wrapper::setParent(layout, %CONVERTTOPYTHON[ObjectTypeLayout*](l)); + Shiboken::Wrapper::setParent(layout, %CONVERTTOPYTHON[ObjectTypeLayout*](l)); } else { - Wrapper::setParent(parent, %CONVERTTOPYTHON[ObjectType*](*it)); + Shiboken::Wrapper::setParent(parent, %CONVERTTOPYTHON[ObjectType*](*it)); } } } @@ -709,8 +709,8 @@ - AutoDecRef _py_ok_(PySequence_GetItem(%PYARG_0, 0)); - AutoDecRef _py_ret_(PySequence_GetItem(%PYARG_0, 1)); + Shiboken::AutoDecRef _py_ok_(PySequence_GetItem(%PYARG_0, 0)); + Shiboken::AutoDecRef _py_ret_(PySequence_GetItem(%PYARG_0, 1)); %RETURN_TYPE %out = %CONVERTTOCPP[%RETURN_TYPE](_py_ok_); %2 = %CONVERTTOCPP[Str*](_py_ret_); @@ -914,7 +914,7 @@ int argc; char** argv; - if (!sequenceToArgcArgv(%PYARG_1, &argc, &argv)) { + if (!Shiboken::sequenceToArgcArgv(%PYARG_1, &argc, &argv)) { PyErr_SetString(PyExc_TypeError, "error"); return 0; } @@ -938,7 +938,7 @@ int argc; char** argv; - if (!sequenceToArgcArgv(%PYARG_1, &argc, &argv)) { + if (!Shiboken::sequenceToArgcArgv(%PYARG_1, &argc, &argv)) { PyErr_SetString(PyExc_TypeError, "error"); return 0; } From 04dea49498d185e4be30987e0790c8b45aaef18b Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 19 Nov 2010 18:01:23 -0200 Subject: [PATCH 140/564] Namespace Shiboken::Wrapper renamed to Shiboken::Object. --- generator/cppgenerator.cpp | 50 +++++++++++------------ generator/headergenerator.cpp | 2 +- libshiboken/basewrapper.cpp | 20 ++++----- libshiboken/basewrapper.h | 10 ++--- libshiboken/basewrapper_p.h | 4 +- libshiboken/bindingmanager.cpp | 2 +- libshiboken/conversions.h | 16 ++++---- tests/samplebinding/typesystem_sample.xml | 6 +-- 8 files changed, 55 insertions(+), 55 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index fe90843f..aaa6d679 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -469,7 +469,7 @@ void CppGenerator::writeDestructorNative(QTextStream &s, const AbstractMetaClass Indentation indentation(INDENT); s << wrapperName(metaClass) << "::~" << wrapperName(metaClass) << "()" << endl << '{' << endl; s << INDENT << "SbkObject* wrapper = Shiboken::BindingManager::instance().retrieveWrapper(this);" << endl; - s << INDENT << "Shiboken::Wrapper::destroy(wrapper);" << endl; + s << INDENT << "Shiboken::Object::destroy(wrapper);" << endl; s << '}' << endl; } @@ -738,7 +738,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu if (invalidateReturn) { s << INDENT << "if (invalidadeArg0)" << endl; Indentation indentation(INDENT); - s << INDENT << "Shiboken::Wrapper::invalidate(" << PYTHON_RETURN_VAR ".object());" << endl; + s << INDENT << "Shiboken::Object::invalidate(" << PYTHON_RETURN_VAR ".object());" << endl; } foreach (FunctionModification funcMod, func->modifications()) { @@ -746,7 +746,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu if (argMod.resetAfterUse) { s << INDENT << "if (invalidadeArg" << argMod.index << ")" << endl; Indentation indentation(INDENT); - s << INDENT << "Shiboken::Wrapper::invalidate(PyTuple_GET_ITEM(pyargs, "; + s << INDENT << "Shiboken::Object::invalidate(PyTuple_GET_ITEM(pyargs, "; s << (argMod.index - 1) << "));" << endl; } } @@ -786,7 +786,7 @@ void CppGenerator::writeMetaObjectMethod(QTextStream& s, const AbstractMetaClass { Indentation indentation(INDENT); s << INDENT << "SbkObject* pySelf = Shiboken::BindingManager::instance().retrieveWrapper(this);\n" - << INDENT << "void* typeData = Shiboken::Wrapper::getTypeUserData(pySelf);" << endl + << INDENT << "void* typeData = Shiboken::Object::getTypeUserData(pySelf);" << endl << INDENT << "if (!typeData) {" << endl; { Indentation indentation2(INDENT); @@ -828,7 +828,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun // Check if the right constructor was called. if (!metaClass->hasPrivateDestructor()) { - s << INDENT << "if (Shiboken::Wrapper::isUserType(self) && !Shiboken::ObjectType::canCallConstructor(self->ob_type, Shiboken::SbkType<" << metaClass->qualifiedCppName() << " >()))" << endl; + s << INDENT << "if (Shiboken::Object::isUserType(self) && !Shiboken::ObjectType::canCallConstructor(self->ob_type, Shiboken::SbkType<" << metaClass->qualifiedCppName() << " >()))" << endl; Indentation indent(INDENT); s << INDENT << "return " << m_currentErrorCode << ';' << endl << endl; } @@ -920,7 +920,7 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun if (hasPythonConvertion) s << INDENT << "}" << endl; - s << INDENT << "if (PyErr_Occurred() || !Shiboken::Wrapper::setCppPointer(sbkSelf, Shiboken::SbkType<" << metaClass->qualifiedCppName() << " >(), cptr)) {" << endl; + s << INDENT << "if (PyErr_Occurred() || !Shiboken::Object::setCppPointer(sbkSelf, Shiboken::SbkType<" << metaClass->qualifiedCppName() << " >(), cptr)) {" << endl; { Indentation indent(INDENT); s << INDENT << "delete cptr;" << endl; @@ -932,13 +932,13 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun s << endl; } - s << INDENT << "Shiboken::Wrapper::setValidCpp(sbkSelf, true);" << endl; + s << INDENT << "Shiboken::Object::setValidCpp(sbkSelf, true);" << endl; // If the created C++ object has a C++ wrapper the ownership is assigned to Python // (first "1") and the flag indicating that the Python wrapper holds an C++ wrapper // is marked as true (the second "1"). Otherwise the default values apply: // Python owns it and C++ wrapper is false. if (shouldGenerateCppWrapper(overloads.first()->ownerClass())) - s << INDENT << "Shiboken::Wrapper::setHasCppWrapper(sbkSelf, true);" << endl; + s << INDENT << "Shiboken::Object::setHasCppWrapper(sbkSelf, true);" << endl; s << INDENT << "Shiboken::BindingManager::instance().registerWrapper(sbkSelf, cptr);" << endl; // Create metaObject and register signal/slot @@ -1171,7 +1171,7 @@ void CppGenerator::writeMethodWrapper(QTextStream& s, const AbstractMetaFunction s << INDENT << "if (!isReverse" << endl; { Indentation indent(INDENT); - s << INDENT << "&& Shiboken::Wrapper::checkType(arg)" << endl; + s << INDENT << "&& Shiboken::Object::checkType(arg)" << endl; s << INDENT << "&& !PyObject_TypeCheck(arg, self->ob_type)" << endl; s << INDENT << "&& PyObject_HasAttrString(arg, const_cast(\"" << revOpName << "\"))) {" << endl; // This PyObject_CallMethod call will emit lots of warnings like @@ -1425,7 +1425,7 @@ void CppGenerator::writeErrorSection(QTextStream& s, OverloadData& overloadData) void CppGenerator::writeInvalidCppObjectCheck(QTextStream& s, QString pyArgName, const TypeEntry* type) { - s << INDENT << "if (!Shiboken::Wrapper::isValid(" << pyArgName << "))" << endl; + s << INDENT << "if (!Shiboken::Object::isValid(" << pyArgName << "))" << endl; Indentation indent(INDENT); s << INDENT << "return " << m_currentErrorCode << ';' << endl; } @@ -1848,7 +1848,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f } if (func->isAbstract()) { - s << INDENT << "if (Shiboken::Wrapper::hasCppWrapper(reinterpret_cast(self))) {\n"; + s << INDENT << "if (Shiboken::Object::hasCppWrapper(reinterpret_cast(self))) {\n"; { Indentation indent(INDENT); s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '"; @@ -2042,7 +2042,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f virtualCall = virtualCall.replace("%CLASS_NAME", func->ownerClass()->qualifiedCppName()); normalCall = normalCall.replace("::%CLASS_NAME::", ""); methodCall = ""; - mc << "(Shiboken::Wrapper::isUserType(self) ? " << virtualCall << ":" << normalCall << ")"; + mc << "(Shiboken::Object::isUserType(self) ? " << virtualCall << ":" << normalCall << ")"; } } } @@ -2126,15 +2126,15 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f s << INDENT; if (arg_mod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::TargetLangOwnership) { - s << "Shiboken::Wrapper::getOwnership(" << pyArgName << ");"; + s << "Shiboken::Object::getOwnership(" << pyArgName << ");"; } else if (wrappedClass->hasVirtualDestructor()) { if (arg_mod.index == 0) { - s << "Shiboken::Wrapper::releaseOwnership(" PYTHON_RETURN_VAR ");"; + s << "Shiboken::Object::releaseOwnership(" PYTHON_RETURN_VAR ");"; } else { - s << "Shiboken::Wrapper::releaseOwnership(" << pyArgName << ");"; + s << "Shiboken::Object::releaseOwnership(" << pyArgName << ");"; } } else { - s << "Shiboken::Wrapper::invalidate(" << pyArgName << ");"; + s << "Shiboken::Object::invalidate(" << pyArgName << ");"; } s << endl; } @@ -2150,7 +2150,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f break; } - s << INDENT << "Shiboken::Wrapper::keepReference(reinterpret_cast(self), \""; + s << INDENT << "Shiboken::Object::keepReference(reinterpret_cast(self), \""; QString varName = arg_mod.referenceCounts.first().varName; if (varName.isEmpty()) varName = func->minimalSignature() + QString().number(arg_mod.index); @@ -2628,7 +2628,7 @@ void CppGenerator::writeCopyFunction(QTextStream& s, const AbstractMetaClass *me s << "static PyObject *" << className << "___copy__(PyObject *self)" << endl; s << "{" << endl; s << INDENT << metaClass->qualifiedCppName() << "* " CPP_SELF_VAR " = 0;" << endl; - s << INDENT << "if (!Shiboken::Wrapper::isValid(self))" << endl; + s << INDENT << "if (!Shiboken::Object::isValid(self))" << endl; { Indentation indent(INDENT); s << INDENT << "return 0;" << endl; @@ -2642,7 +2642,7 @@ void CppGenerator::writeCopyFunction(QTextStream& s, const AbstractMetaClass *me s << INDENT << PYTHON_RETURN_VAR " = Shiboken::Converter<" << metaClass->qualifiedCppName(); s << "*>::toPython(copy);" << endl; - s << INDENT << "Shiboken::Wrapper::getOwnership(" PYTHON_RETURN_VAR ");" << endl; + s << INDENT << "Shiboken::Object::getOwnership(" PYTHON_RETURN_VAR ");" << endl; s << endl; @@ -2724,7 +2724,7 @@ void CppGenerator::writeSetterFunction(QTextStream& s, const AbstractMetaField* bool pythonWrapperRefCounting = metaField->type()->typeEntry()->isObject() || metaField->type()->isValuePointer(); if (pythonWrapperRefCounting) { - s << INDENT << "Shiboken::Wrapper::keepReference(reinterpret_cast(self), \""; + s << INDENT << "Shiboken::Object::keepReference(reinterpret_cast(self), \""; s << metaField->name() << "\", value);" << endl; //s << INDENT << "Py_XDECREF(oldvalue);" << endl; s << endl; @@ -3805,7 +3805,7 @@ bool CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMeta else childVariable = usePyArgs ? "pyargs["+QString::number(childIndex-1)+"]" : "arg"; - s << INDENT << "Shiboken::Wrapper::setParent(" << parentVariable << ", " << childVariable << ");\n"; + s << INDENT << "Shiboken::Object::setParent(" << parentVariable << ", " << childVariable << ");\n"; return true; } @@ -3839,7 +3839,7 @@ void CppGenerator::writeReturnValueHeuristics(QTextStream& s, const AbstractMeta } if (type->isQObject() || type->isObject() || type->isValuePointer()) - s << INDENT << "Shiboken::Wrapper::setParent(" << self << ", " PYTHON_RETURN_VAR ");" << endl; + s << INDENT << "Shiboken::Object::setParent(" << self << ", " PYTHON_RETURN_VAR ");" << endl; } void CppGenerator::writeHashFunction(QTextStream& s, const AbstractMetaClass* metaClass) @@ -3867,7 +3867,7 @@ void CppGenerator::writeStdListWrapperMethods(QTextStream& s, const AbstractMeta { //len s << "Py_ssize_t " << cpythonBaseName(metaClass->typeEntry()) << "__len__" << "(PyObject* self)" << endl << '{' << endl; - s << INDENT << "if (!Shiboken::Wrapper::isValid(self))" << endl; + s << INDENT << "if (!Shiboken::Object::isValid(self))" << endl; s << INDENT << INDENT << "return 0;" << endl << endl; s << INDENT << metaClass->qualifiedCppName() << " &cppSelf = Shiboken::Converter<" << metaClass->qualifiedCppName() <<"& >::toCpp(self);" << endl; s << INDENT << "return cppSelf.size();" << endl; @@ -3875,7 +3875,7 @@ void CppGenerator::writeStdListWrapperMethods(QTextStream& s, const AbstractMeta //getitem s << "PyObject* " << cpythonBaseName(metaClass->typeEntry()) << "__getitem__" << "(PyObject* self, Py_ssize_t _i)" << endl << '{' << endl; - s << INDENT << "if (!Shiboken::Wrapper::isValid(self))" << endl; + s << INDENT << "if (!Shiboken::Object::isValid(self))" << endl; s << INDENT << INDENT << "return 0;" << endl << endl; s << INDENT << metaClass->qualifiedCppName() << " &cppSelf = Shiboken::Converter<" << metaClass->qualifiedCppName() <<"& >::toCpp(self);" << endl; s << INDENT << "if (_i < 0 || _i >= (Py_ssize_t) cppSelf.size()) {" << endl; @@ -3888,7 +3888,7 @@ void CppGenerator::writeStdListWrapperMethods(QTextStream& s, const AbstractMeta //setitem s << "int " << cpythonBaseName(metaClass->typeEntry()) << "__setitem__" << "(PyObject* self, Py_ssize_t _i, PyObject* _value)" << endl << '{' << endl; - s << INDENT << "if (!Shiboken::Wrapper::isValid(self))" << endl; + s << INDENT << "if (!Shiboken::Object::isValid(self))" << endl; s << INDENT << INDENT << "return -1;" << endl; s << INDENT << metaClass->qualifiedCppName() << " &cppSelf = Shiboken::Converter<" << metaClass->qualifiedCppName() <<"& >::toCpp(self);" << endl; s << INDENT << "if (_i < 0 || _i >= (Py_ssize_t) cppSelf.size()) {" << endl; diff --git a/generator/headergenerator.cpp b/generator/headergenerator.cpp index 3f14712b..4775331c 100644 --- a/generator/headergenerator.cpp +++ b/generator/headergenerator.cpp @@ -434,7 +434,7 @@ void HeaderGenerator::finishGeneration() s << INDENT << metaClass->qualifiedCppName() << "* value = const_cast<" << metaClass->qualifiedCppName() << "* >(cppobj);" << endl; s << INDENT << "if (!isExactType)" << endl; s << INDENT << INDENT << "typeName = typeid(*value).name();" << endl; - s << INDENT << "PyObject* pyObj = Shiboken::Wrapper::newObject(reinterpret_cast(SbkType< ::" << metaClass->qualifiedCppName() << " >())," + s << INDENT << "PyObject* pyObj = Shiboken::Object::newObject(reinterpret_cast(SbkType< ::" << metaClass->qualifiedCppName() << " >())," << "value, hasOwnership, isExactType, typeName);" << endl; s << INDENT << "PySide::Signal::updateSourceObject(pyObj);" << endl; s << INDENT << "return pyObj;" << endl; diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 948a24e3..a19d569c 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -170,7 +170,7 @@ void SbkDeallocWrapper(PyObject* pyObj) } } - Shiboken::Wrapper::deallocData(sbkObj); + Shiboken::Object::deallocData(sbkObj); } void SbkDeallocWrapperWithPrivateDtor(PyObject* self) @@ -180,7 +180,7 @@ void SbkDeallocWrapperWithPrivateDtor(PyObject* self) PyObject_ClearWeakRefs(self); Shiboken::BindingManager::instance().releaseWrapper(sbkObj); - Shiboken::Wrapper::deallocData(sbkObj); + Shiboken::Object::deallocData(sbkObj); } void SbkBaseTypeDealloc(PyObject* pyObj) @@ -407,7 +407,7 @@ std::list splitPyObject(PyObject* pyObj) if (!lst.isNull()) { for(int i = 0, i_max = PySequence_Fast_GET_SIZE(lst.object()); i < i_max; i++) { PyObject* item = PySequence_Fast_GET_ITEM(lst.object(), i); - if (Wrapper::checkType(item)) + if (Object::checkType(item)) result.push_back(reinterpret_cast(item)); } } @@ -503,7 +503,7 @@ bool hasCast(SbkObjectType* self) void* cast(SbkObjectType* self, SbkObject* obj, PyTypeObject *target) { - return self->d->mi_specialcast(Wrapper::cppPointer(obj, target), reinterpret_cast(target)); + return self->d->mi_specialcast(Object::cppPointer(obj, target), reinterpret_cast(target)); } void setCastFunction(SbkObjectType* self, SpecialCastFunction func) @@ -563,7 +563,7 @@ void initPrivateData(SbkObjectType* self) } // namespace ObjectType -namespace Wrapper +namespace Object { bool checkType(PyObject* pyObj) @@ -587,7 +587,7 @@ static void setSequenceOwnership(PyObject* pyObj, bool owner) else releaseOwnership(*it); } - } else if (Wrapper::checkType(pyObj)) { + } else if (Object::checkType(pyObj)) { if (owner) getOwnership(reinterpret_cast(pyObj)); else @@ -603,7 +603,7 @@ static void _destroyParentInfo(SbkObject* obj, bool keepReference) while(!pInfo->children.empty()) { SbkObject* first = pInfo->children.front(); // Mark child as invalid - Shiboken::Wrapper::invalidate(first); + Shiboken::Object::invalidate(first); removeParent(first, false, keepReference); } removeParent(obj, false); @@ -877,7 +877,7 @@ void setParent(PyObject* parent, PyObject* child) * so if you pass this class to someone that takes the ownership, we CAN'T enter in this if, but hey! QString * follows the sequence protocol. */ - if (PySequence_Check(child) && !Wrapper::checkType(child)) { + if (PySequence_Check(child) && !Object::checkType(child)) { Shiboken::AutoDecRef seq(PySequence_Fast(child, 0)); for (int i = 0, max = PySequence_Size(seq); i < max; ++i) setParent(parent, PySequence_Fast_GET_ITEM(seq.object(), i)); @@ -949,14 +949,14 @@ void deallocData(SbkObject* self) Py_TYPE(self)->tp_free(self); } -void setTypeUserData(SbkObject* wrapper, void *user_data, DeleteUserDataFunc d_func) +void setTypeUserData(SbkObject* wrapper, void* userData, DeleteUserDataFunc d_func) { SbkObjectType* ob_type = reinterpret_cast(wrapper->ob_type); if (ob_type->d->user_data) ob_type->d->d_func(ob_type->d->user_data); ob_type->d->d_func = d_func; - ob_type->d->user_data = user_data; + ob_type->d->user_data = userData; } void* getTypeUserData(SbkObject* wrapper) diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 7ae5502f..cdc5f484 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -129,7 +129,7 @@ LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject* myType, PyTypeObjec /** * Call copy function for the object type **/ -LIBSHIBOKEN_API void* copy(SbkObjectType* self, const void *obj); +LIBSHIBOKEN_API void* copy(SbkObjectType* self, const void* obj); LIBSHIBOKEN_API void setCopyFunction(SbkObjectType* self, ObjectCopierFunction func); LIBSHIBOKEN_API void setExternalCppConversionFunction(SbkObjectType* self, ExtendedToCppFunc func); @@ -157,7 +157,7 @@ LIBSHIBOKEN_API void setDestructorFunction(SbkObjectType* self, ObjectDes LIBSHIBOKEN_API void initPrivateData(SbkObjectType* self); } -namespace Wrapper { +namespace Object { /** * Returns true if the object is an instance of a type created by the Shiboken generator. @@ -242,7 +242,7 @@ LIBSHIBOKEN_API void destroy(SbkObject* self); /** * Get/Set Userdata in type class */ -LIBSHIBOKEN_API void setTypeUserData(SbkObject* wrapper, void* user_data, DeleteUserDataFunc d_func); +LIBSHIBOKEN_API void setTypeUserData(SbkObject* wrapper, void* userData, DeleteUserDataFunc d_func); LIBSHIBOKEN_API void* getTypeUserData(SbkObject* wrapper); /** @@ -257,9 +257,9 @@ LIBSHIBOKEN_API void* getTypeUserData(SbkObject* wrapper); * \param key a key that identifies the C++ method signature and argument where the referredObject came from. * \parem referredObject the object whose reference is used by the self object. */ -LIBSHIBOKEN_API void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append=false); +LIBSHIBOKEN_API void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append = false); -} // namespace Wrapper +} // namespace Object } // namespace Shiboken diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h index ebf50d44..45fdb876 100644 --- a/libshiboken/basewrapper_p.h +++ b/libshiboken/basewrapper_p.h @@ -218,7 +218,7 @@ inline std::list getCppBaseClasses(PyTypeObject* baseType) return visitor.bases(); } -namespace Wrapper +namespace Object { /** * Decrements the reference counters of every object referred by self. @@ -230,7 +230,7 @@ void clearReferences(SbkObject* self); * Destroy internal data **/ void deallocData(SbkObject* self); -} // namespace Wrapper +} // namespace Object } // namespace Shiboken diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index dd9fb5d1..f0797042 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -148,7 +148,7 @@ BindingManager::~BindingManager() * the BindingManager is being destroyed the interpreter is alredy * shutting down. */ while (!m_d->wrapperMapper.empty()) { - Wrapper::destroy(m_d->wrapperMapper.begin()->second); + Object::destroy(m_d->wrapperMapper.begin()->second); } assert(m_d->wrapperMapper.size() == 0); delete m_d; diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index 5d0048fe..a49ec34d 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -113,7 +113,7 @@ inline PyObject* createWrapper(const T* cppobj, bool hasOwnership = false, bool const char* typeName = 0; if (!isExactType) typeName = typeid(*const_cast(cppobj)).name(); - return Wrapper::newObject(reinterpret_cast(SbkType()), + return Object::newObject(reinterpret_cast(SbkType()), const_cast(cppobj), hasOwnership, isExactType, typeName); } @@ -150,7 +150,7 @@ struct Converter static T* toCpp(PyObject* pyobj) { if (PyObject_TypeCheck(pyobj, SbkType())) - return (T*) Wrapper::cppPointer(reinterpret_cast(pyobj), SbkType()); + return (T*) Object::cppPointer(reinterpret_cast(pyobj), SbkType()); else if (Converter::isConvertible(pyobj)) return CppObjectCopier::copy(Converter::toCpp(pyobj)); else if (pyobj == Py_None) @@ -239,7 +239,7 @@ struct ValueTypeConverter } assert(false); } - return *reinterpret_cast(Wrapper::cppPointer(reinterpret_cast(pyobj), SbkType())); + return *reinterpret_cast(Object::cppPointer(reinterpret_cast(pyobj), SbkType())); } }; @@ -274,7 +274,7 @@ struct ObjectTypeConverter SbkObjectType* shiboType = reinterpret_cast(pyobj->ob_type); if (ObjectType::hasCast(shiboType)) return reinterpret_cast(ObjectType::cast(shiboType, reinterpret_cast(pyobj), SbkType())); - return (T*) Wrapper::cppPointer(reinterpret_cast(pyobj), SbkType()); + return (T*) Object::cppPointer(reinterpret_cast(pyobj), SbkType()); } }; @@ -560,7 +560,7 @@ struct StdListConverter // binded types implementing sequence protocol, otherwise this will // cause a mess like QBitArray being accepted by someone expecting a // QStringList. - if ((SbkType() && Wrapper::checkType(pyObj)) || !PySequence_Check(pyObj)) + if ((SbkType() && Object::checkType(pyObj)) || !PySequence_Check(pyObj)) return false; for (int i = 0, max = PySequence_Length(pyObj); i < max; ++i) { AutoDecRef item(PySequence_GetItem(pyObj, i)); @@ -583,7 +583,7 @@ struct StdListConverter static StdList toCpp(PyObject* pyobj) { if (PyObject_TypeCheck(pyobj, SbkType())) - return *reinterpret_cast(Wrapper::cppPointer(reinterpret_cast(pyobj), SbkType())); + return *reinterpret_cast(Object::cppPointer(reinterpret_cast(pyobj), SbkType())); StdList result; for (int i = 0; i < PySequence_Size(pyobj); i++) { @@ -606,7 +606,7 @@ struct StdPairConverter { if (PyObject_TypeCheck(pyObj, SbkType())) return true; - if ((SbkType() && Wrapper::checkType(pyObj)) || !PySequence_Check(pyObj) || PySequence_Length(pyObj) != 2) + if ((SbkType() && Object::checkType(pyObj)) || !PySequence_Check(pyObj) || PySequence_Length(pyObj) != 2) return false; AutoDecRef item1(PySequence_GetItem(pyObj, 0)); @@ -651,7 +651,7 @@ struct StdMapConverter { if (PyObject_TypeCheck(pyObj, SbkType())) return true; - if ((SbkType() && Wrapper::checkType(pyObj)) || !PyDict_Check(pyObj)) + if ((SbkType() && Object::checkType(pyObj)) || !PyDict_Check(pyObj)) return false; PyObject* key; diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index fb46eb2f..c54da989 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -178,9 +178,9 @@ if ((*it)->isLayoutType()) { ObjectTypeLayout* l = reinterpret_cast<ObjectTypeLayout*>(*it); reparent_layout_items(parent, %CONVERTTOPYTHON[ObjectTypeLayout*](l)); - Shiboken::Wrapper::setParent(layout, %CONVERTTOPYTHON[ObjectTypeLayout*](l)); + Shiboken::Object::setParent(layout, %CONVERTTOPYTHON[ObjectTypeLayout*](l)); } else { - Shiboken::Wrapper::setParent(parent, %CONVERTTOPYTHON[ObjectType*](*it)); + Shiboken::Object::setParent(parent, %CONVERTTOPYTHON[ObjectType*](*it)); } } } @@ -1176,7 +1176,7 @@ %RETURN_TYPE %0 = %TYPE::%FUNCTION_NAME(); - %PYARG_0 = Shiboken::Wrapper::newObject(&SbkObject_Type, %0, false, false); + %PYARG_0 = Shiboken::Object::newObject(&SbkObject_Type, %0, false, false); From 2a3262852ad7f44648624e1c2f20393fa02019da Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 19 Nov 2010 19:01:13 -0200 Subject: [PATCH 141/564] Renamed some more internal objects and functions. --- libshiboken/basewrapper.cpp | 22 +++++++++++----------- libshiboken/basewrapper.h | 4 ++-- libshiboken/basewrapper_p.h | 2 +- libshiboken/bindingmanager.cpp | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index a19d569c..1afa5529 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -34,8 +34,8 @@ extern "C" { -static void SbkBaseTypeDealloc(PyObject* pyObj); -static PyObject* SbkBaseTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds); +static void SbkObjectTypeDealloc(PyObject* pyObj); +static PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds); PyTypeObject SbkBaseType_Type = { PyObject_HEAD_INIT(0) @@ -43,7 +43,7 @@ PyTypeObject SbkBaseType_Type = { /*tp_name*/ "Shiboken.ObjectType", /*tp_basicsize*/ sizeof(SbkObjectType), /*tp_itemsize*/ 0, - /*tp_dealloc*/ SbkBaseTypeDealloc, + /*tp_dealloc*/ SbkObjectTypeDealloc, /*tp_print*/ 0, /*tp_getattr*/ 0, /*tp_setattr*/ 0, @@ -76,7 +76,7 @@ PyTypeObject SbkBaseType_Type = { /*tp_dictoffset*/ 0, /*tp_init*/ 0, /*tp_alloc*/ 0, - /*tp_new*/ SbkBaseTypeTpNew, + /*tp_new*/ SbkObjectTypeTpNew, /*tp_free*/ 0, /*tp_is_gc*/ 0, /*tp_bases*/ 0, @@ -183,7 +183,7 @@ void SbkDeallocWrapperWithPrivateDtor(PyObject* self) Shiboken::Object::deallocData(sbkObj); } -void SbkBaseTypeDealloc(PyObject* pyObj) +void SbkObjectTypeDealloc(PyObject* pyObj) { SbkObjectType* sbkType = reinterpret_cast(pyObj->ob_type); if (!sbkType->d) @@ -199,7 +199,7 @@ void SbkBaseTypeDealloc(PyObject* pyObj) sbkType->d = 0; } -PyObject* SbkBaseTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds) +PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds) { // The meta type creates a new type when the Python programmer extends a wrapped C++ class. SbkObjectType* newType = reinterpret_cast(PyType_Type.tp_new(metatype, args, kwds)); @@ -207,12 +207,12 @@ PyObject* SbkBaseTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwd if (!newType) return 0; - SbkBaseTypePrivate* d = new SbkBaseTypePrivate; - memset(d, 0, sizeof(SbkBaseTypePrivate)); + SbkObjectTypePrivate* d = new SbkObjectTypePrivate; + memset(d, 0, sizeof(SbkObjectTypePrivate)); std::list bases = Shiboken::getCppBaseClasses(reinterpret_cast(newType)); if (bases.size() == 1) { - SbkBaseTypePrivate* parentType = bases.front()->d; + SbkObjectTypePrivate* parentType = bases.front()->d; d->mi_offsets = parentType->mi_offsets; d->mi_init = parentType->mi_init; d->mi_specialcast = parentType->mi_specialcast; @@ -557,8 +557,8 @@ void setDestructorFunction(SbkObjectType* self, ObjectDestructor func) void initPrivateData(SbkObjectType* self) { - self->d = new SbkBaseTypePrivate; - memset(self->d, 0, sizeof(SbkBaseTypePrivate)); + self->d = new SbkObjectTypePrivate; + memset(self->d, 0, sizeof(SbkObjectTypePrivate)); } } // namespace ObjectType diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index cdc5f484..d41e7ea6 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -77,12 +77,12 @@ extern LIBSHIBOKEN_API PyTypeObject SbkBaseType_Type; extern LIBSHIBOKEN_API SbkObjectType SbkObject_Type; -struct SbkBaseTypePrivate; +struct SbkObjectTypePrivate; /// PyTypeObject extended with C++ multiple inheritance information. struct LIBSHIBOKEN_API SbkObjectType { PyHeapTypeObject super; - SbkBaseTypePrivate* d; + SbkObjectTypePrivate* d; }; LIBSHIBOKEN_API PyObject* SbkObjectTpNew(PyTypeObject* subtype, PyObject*, PyObject*); diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h index 45fdb876..6637e4f7 100644 --- a/libshiboken/basewrapper_p.h +++ b/libshiboken/basewrapper_p.h @@ -81,7 +81,7 @@ struct SbkObjectPrivate }; -struct SbkBaseTypePrivate +struct SbkObjectTypePrivate { int* mi_offsets; MultipleInheritanceInitFunction mi_init; diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index f0797042..9f73833c 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -167,7 +167,7 @@ bool BindingManager::hasWrapper(const void* cptr) void BindingManager::registerWrapper(SbkObject* pyObj, void* cptr) { SbkObjectType* instanceType = reinterpret_cast(pyObj->ob_type); - SbkBaseTypePrivate* d = instanceType->d; + SbkObjectTypePrivate* d = instanceType->d; if (!d) return; @@ -188,7 +188,7 @@ void BindingManager::registerWrapper(SbkObject* pyObj, void* cptr) void BindingManager::releaseWrapper(SbkObject* sbkObj) { SbkObjectType* sbkType = reinterpret_cast(sbkObj->ob_type); - SbkBaseTypePrivate* d = sbkType->d; + SbkObjectTypePrivate* d = sbkType->d; int numBases = ((d && d->is_multicpp) ? getNumberOfCppBaseClasses(sbkObj->ob_type) : 1); void** cptrs = reinterpret_cast(sbkObj)->d->cptr; From 622e6f61a08b8ef31dd996609d69812f53e566b8 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 19 Nov 2010 19:04:30 -0200 Subject: [PATCH 142/564] SbkBaseType_Type renamed to SbkObjectType_Type. --- generator/cppgenerator.cpp | 2 +- libshiboken/basewrapper.cpp | 12 ++++++------ libshiboken/basewrapper.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index aaa6d679..6e7ba558 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2413,7 +2413,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* s << "// Class Definition -----------------------------------------------" << endl; s << "extern \"C\" {" << endl; s << "static SbkObjectType " << className + "_Type" << " = { { {" << endl; - s << INDENT << "PyObject_HEAD_INIT(&SbkBaseType_Type)" << endl; + s << INDENT << "PyObject_HEAD_INIT(&SbkObjectType_Type)" << endl; s << INDENT << "/*ob_size*/ 0," << endl; s << INDENT << "/*tp_name*/ \"" << metaClass->fullName() << "\"," << endl; s << INDENT << "/*tp_basicsize*/ sizeof(SbkObject)," << endl; diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 1afa5529..48ed8084 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -37,7 +37,7 @@ extern "C" static void SbkObjectTypeDealloc(PyObject* pyObj); static PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* kwds); -PyTypeObject SbkBaseType_Type = { +PyTypeObject SbkObjectType_Type = { PyObject_HEAD_INIT(0) /*ob_size*/ 0, /*tp_name*/ "Shiboken.ObjectType", @@ -102,7 +102,7 @@ static PyGetSetDef SbkObjectGetSetList[] = { }; SbkObjectType SbkObject_Type = { { { - PyObject_HEAD_INIT(&SbkBaseType_Type) + PyObject_HEAD_INIT(&SbkObjectType_Type) /*ob_size*/ 0, /*tp_name*/ "Shiboken.Object", /*tp_basicsize*/ sizeof(SbkObject), @@ -279,7 +279,7 @@ void walkThroughClassHierarchy(PyTypeObject* currentType, HierarchyVisitor* visi for (int i = 0; i < numBases; ++i) { PyTypeObject* type = reinterpret_cast(PyTuple_GET_ITEM(bases, i)); - if (type->ob_type != &SbkBaseType_Type) { + if (type->ob_type != &SbkObjectType_Type) { continue; } else { SbkObjectType* sbkType = reinterpret_cast(type); @@ -331,7 +331,7 @@ void init() if (PyType_Ready(&SbkEnumType_Type) < 0) Py_FatalError("[libshiboken] Failed to initialise Shiboken.SbkEnumType metatype."); - if (PyType_Ready(&SbkBaseType_Type) < 0) + if (PyType_Ready(&SbkObjectType_Type) < 0) Py_FatalError("[libshiboken] Failed to initialise Shiboken.BaseWrapperType metatype."); if (PyType_Ready((PyTypeObject *)&SbkObject_Type) < 0) @@ -442,7 +442,7 @@ namespace ObjectType bool checkType(PyTypeObject* type) { - return type->ob_type == &SbkBaseType_Type; + return type->ob_type == &SbkObjectType_Type; } bool isUserType(PyTypeObject* type) @@ -763,7 +763,7 @@ bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desiredType, void* cptr) bool isValid(PyObject* pyObj) { if (!pyObj || pyObj == Py_None - || pyObj->ob_type->ob_type != &SbkBaseType_Type + || pyObj->ob_type->ob_type != &SbkObjectType_Type || ((SbkObject*)pyObj)->d->validCppObject) { return true; } diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index d41e7ea6..460f3159 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -73,7 +73,7 @@ typedef void (*DeleteUserDataFunc)(void*); typedef void (*ObjectDestructor)(void*); -extern LIBSHIBOKEN_API PyTypeObject SbkBaseType_Type; +extern LIBSHIBOKEN_API PyTypeObject SbkObjectType_Type; extern LIBSHIBOKEN_API SbkObjectType SbkObject_Type; From 605bbf8d03eaf5c90b1efdb17eabfa66fedc24be Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 23 Nov 2010 13:35:42 -0200 Subject: [PATCH 143/564] Do not use const and ref when writing converters for object-types, qflags, const ref. value types and enums. --- generator/shibokengenerator.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/generator/shibokengenerator.cpp b/generator/shibokengenerator.cpp index 5ddbb6d7..b064573d 100644 --- a/generator/shibokengenerator.cpp +++ b/generator/shibokengenerator.cpp @@ -476,7 +476,7 @@ static QString baseConversionString(QString typeName) void ShibokenGenerator::writeBaseConversion(QTextStream& s, const TypeEntry* type) { - QString typeName = type->qualifiedCppName(); + QString typeName = type->qualifiedCppName().trimmed(); if (!type->isCppPrimitive()) typeName.prepend("::"); if (type->isObject()) @@ -501,11 +501,11 @@ void ShibokenGenerator::writeBaseConversion(QTextStream& s, const AbstractMetaTy ptype = ptype->basicAliasedTypeEntry(); typeName = ptype->name(); } else { - if (type->isObject() || (type->isValue() && !type->isReference())) + if (!isCString(type)) // not "const char*" options |= Generator::ExcludeConst; - if (type->isContainer() || (type->isConstant() && type->isReference())) - options |= Generator::ExcludeReference | Generator::ExcludeConst; - typeName = translateTypeForWrapperMethod(type, context, options); + if (type->isContainer() || type->isFlags() || type->isEnum() || (type->isConstant() && type->isReference())) + options |= Generator::ExcludeReference; + typeName = translateTypeForWrapperMethod(type, context, options).trimmed(); if (!type->typeEntry()->isCppPrimitive()) typeName.prepend("::"); } From cecb22759c6144c9e28921a18cb5255db9771e28 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Tue, 23 Nov 2010 15:03:46 -0300 Subject: [PATCH 144/564] Fixed generation with use of protect hack. --- generator/cppgenerator.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index fa8b2cc2..f4a4918e 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2025,7 +2025,6 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f if (!func->isAbstract() && func->isVirtual()) mc << "::%CLASS_NAME::"; - mc << func->originalName(); #ifdef AVOID_PROTECTED_HACK @@ -2044,7 +2043,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f mc << '(' << userArgs.join(", ") << ')'; if (!func->isAbstract() && func->isVirtual()) { mc.flush(); -#ifndef AVOID_PROTECTED_HACK +#ifdef AVOID_PROTECTED_HACK if (!func->isProtected()) #endif { From fd81c050afca0ff3190e852062837be05017f00f Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 23 Nov 2010 15:36:38 -0200 Subject: [PATCH 145/564] Fix compilation without protect hack. Reviewer: Marcelo Lira Luciano Wolf --- generator/headergenerator.cpp | 27 ++++++++++++++++++++++----- generator/headergenerator.h | 1 + 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/generator/headergenerator.cpp b/generator/headergenerator.cpp index 4775331c..3e242cc1 100644 --- a/generator/headergenerator.cpp +++ b/generator/headergenerator.cpp @@ -214,8 +214,8 @@ void HeaderGenerator::writeTypeConverterDecl(QTextStream& s, const TypeEntry* ty } bool isValueTypeWithImplConversions = type->isValue() && !implicitConvs.isEmpty(); bool hasCustomConversion = type->hasNativeConversionRule(); - QString typeT = "::" + type->qualifiedCppName() + (isAbstractOrObjectType ? "*" : ""); - QString typeName = "::" + type->qualifiedCppName(); + QString typeT = type->qualifiedCppName() + (isAbstractOrObjectType ? "*" : ""); + QString typeName = type->qualifiedCppName(); #ifdef AVOID_PROTECTED_HACK const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(type); @@ -224,6 +224,8 @@ void HeaderGenerator::writeTypeConverterDecl(QTextStream& s, const TypeEntry* ty typeName = typeT; } #endif + typeT.prepend("::"); + typeName.prepend("::"); s << "struct Converter< " << typeT << " >"; if (!hasCustomConversion) { @@ -304,6 +306,8 @@ void HeaderGenerator::finishGeneration() QTextStream typeFunctions(&sbkTypeFunctions); QString converterImpl; QTextStream convImpl(&converterImpl); + QString protectedEnumSurrogates; + QTextStream protEnumsSurrogates(&protectedEnumSurrogates); Indentation indent(INDENT); @@ -328,6 +332,7 @@ void HeaderGenerator::finishGeneration() includes << cppEnum->typeEntry()->include(); writeTypeConverterDecl(convDecl, cppEnum->typeEntry()); convDecl << endl; + writeProtectedEnumSurrogate(protEnumsSurrogates, cppEnum); writeSbkTypeFunction(typeFunctions, cppEnum); } @@ -349,6 +354,7 @@ void HeaderGenerator::finishGeneration() if (flagsEntry) writeTypeConverterDecl(convDecl, flagsEntry); convDecl << endl; + writeProtectedEnumSurrogate(protEnumsSurrogates, cppEnum); writeSbkTypeFunction(typeFunctions, cppEnum); } @@ -416,6 +422,11 @@ void HeaderGenerator::finishGeneration() s << macros << endl; + if (!protectedEnumSurrogates.isEmpty()) { + s << "// Protected enum surrogates" << endl; + s << protectedEnumSurrogates << endl; + } + s << "namespace Shiboken" << endl << '{' << endl << endl; s << "// PyType functions, to get the PyObjectType for a type T\n"; @@ -460,16 +471,22 @@ void HeaderGenerator::finishGeneration() s << "#endif // " << includeShield << endl << endl; } +void HeaderGenerator::writeProtectedEnumSurrogate(QTextStream& s, const AbstractMetaEnum* cppEnum) +{ +#ifdef AVOID_PROTECTED_HACK + if (cppEnum->isProtected()) + s << "enum " << protectedEnumSurrogateName(cppEnum) << " {};" << endl; +#endif +} + void HeaderGenerator::writeSbkTypeFunction(QTextStream& s, const AbstractMetaEnum* cppEnum) { QString enumName = cppEnum->name(); if (cppEnum->enclosingClass()) enumName = cppEnum->enclosingClass()->qualifiedCppName() + "::" + enumName; #ifdef AVOID_PROTECTED_HACK - if (cppEnum->isProtected()) { + if (cppEnum->isProtected()) enumName = protectedEnumSurrogateName(cppEnum); - s << "enum " << enumName << " {};" << endl; - } #endif s << "template<> inline PyTypeObject* SbkType< ::" << enumName << " >() "; diff --git a/generator/headergenerator.h b/generator/headergenerator.h index 9802a104..96d63c64 100644 --- a/generator/headergenerator.h +++ b/generator/headergenerator.h @@ -51,6 +51,7 @@ class HeaderGenerator : public ShibokenGenerator void writeTypeIndexDefineLine(QTextStream& s, const TypeEntry* typeEntry, int& idx); void writeTypeIndexDefine(QTextStream& s, const AbstractMetaClass* metaClass, int& idx); void writeTypeConverterImpl(QTextStream& s, const TypeEntry* type); + void writeProtectedEnumSurrogate(QTextStream& s, const AbstractMetaEnum* cppEnum); }; From db4316721ebdccf3a782c4888fb01d4407c51b71 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 23 Nov 2010 17:43:51 -0200 Subject: [PATCH 146/564] Fix value of variable AVOID_PROTECTED_HACK. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Luciano Wolf Renato Araújo --- data/ShibokenConfig.cmake.in | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/data/ShibokenConfig.cmake.in b/data/ShibokenConfig.cmake.in index 50d14c9f..24f23abb 100644 --- a/data/ShibokenConfig.cmake.in +++ b/data/ShibokenConfig.cmake.in @@ -19,8 +19,9 @@ SET(SHIBOKEN_BUILD_TYPE "@SHIBOKEN_BUILD_TYPE@") message(STATUS "libshiboken built for @SHIBOKEN_BUILD_TYPE@") @SBK_ADD_PY_DEBUG_DEFINITION@ -option(AVOID_PROTECTED_HACK "Avoid protected hack on generated bindings." FALSE) -if(AVOID_PROTECTED_HACK OR WIN32) +# We don't use just "if (@AVOID_PROTECTED_HACK@)" to avoid require all users to turn on the cmake policy CMP0012 +# for more info type: cmake --help-policy CMP0012 +if ("@AVOID_PROTECTED_HACK@" STREQUAL "TRUE") add_definitions(-DAVOID_PROTECTED_HACK) message(STATUS "Avoiding protected hack!") endif() From 23de22f194dd1e5dfccce0cc03302af4f4018727 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 23 Nov 2010 17:43:51 -0200 Subject: [PATCH 147/564] Fix last commit, compre was a fragile and stupid solution. --- data/ShibokenConfig.cmake.in | 3 ++- data/shiboken.pc.in | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/data/ShibokenConfig.cmake.in b/data/ShibokenConfig.cmake.in index 24f23abb..c7abc831 100644 --- a/data/ShibokenConfig.cmake.in +++ b/data/ShibokenConfig.cmake.in @@ -21,7 +21,8 @@ message(STATUS "libshiboken built for @SHIBOKEN_BUILD_TYPE@") # We don't use just "if (@AVOID_PROTECTED_HACK@)" to avoid require all users to turn on the cmake policy CMP0012 # for more info type: cmake --help-policy CMP0012 -if ("@AVOID_PROTECTED_HACK@" STREQUAL "TRUE") +set(SHIBOKEN_AVOID_PROTECTED_HACK @AVOID_PROTECTED_HACK@) +if (SHIBOKEN_AVOID_PROTECTED_HACK) add_definitions(-DAVOID_PROTECTED_HACK) message(STATUS "Avoiding protected hack!") endif() diff --git a/data/shiboken.pc.in b/data/shiboken.pc.in index 5fb4ab0d..639a224d 100644 --- a/data/shiboken.pc.in +++ b/data/shiboken.pc.in @@ -5,6 +5,7 @@ includedir=@CMAKE_INSTALL_PREFIX@/include/shiboken generator_location=@CMAKE_INSTALL_PREFIX@/bin/shiboken python_interpreter=@PYTHON_EXECUTABLE@ python_include_dir=@PYTHON_INCLUDE_DIR@ +avoid_protected_hack=@AVOID_PROTECTED_HACK@ Name: shiboken Description: Support library for Python bindings created with Shiboken generator. From 2651ec7b04923db3c64ff59fcc5cb9c966d685f6 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 24 Nov 2010 14:19:59 -0200 Subject: [PATCH 148/564] Speed up hasWrapper function using the find method instead of count. --- libshiboken/bindingmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index 9f73833c..a4385261 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -161,7 +161,7 @@ BindingManager& BindingManager::instance() { bool BindingManager::hasWrapper(const void* cptr) { - return m_d->wrapperMapper.count(cptr); + return m_d->wrapperMapper.find(cptr) != m_d->wrapperMapper.end(); } void BindingManager::registerWrapper(SbkObject* pyObj, void* cptr) From ac10a67837433328f6a9ca51475a2eb7e29e4e03 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 24 Nov 2010 14:20:44 -0200 Subject: [PATCH 149/564] Added BindingManager::visitAllPyObjects function, used to visit all PyObjects with a function. Reviewer: Marcelo Lira Luciano Wolf --- libshiboken/bindingmanager.cpp | 9 +++++++++ libshiboken/bindingmanager.h | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index a4385261..2bcf2deb 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -277,5 +277,14 @@ std::set BindingManager::getAllPyObjects() return pyObjects; } +void BindingManager::visitAllPyObjects(ObjectVisitor visitor, void* data) +{ + WrapperMap copy = m_d->wrapperMapper; + for (WrapperMap::iterator it = copy.begin(); it != copy.end(); ++it) { + if (hasWrapper(it->first)) + visitor(it->second, data); + } +} + } // namespace Shiboken diff --git a/libshiboken/bindingmanager.h b/libshiboken/bindingmanager.h index b6d4ac42..e12558b4 100644 --- a/libshiboken/bindingmanager.h +++ b/libshiboken/bindingmanager.h @@ -33,6 +33,8 @@ struct SbkObjectType; namespace Shiboken { +typedef void (*ObjectVisitor)(SbkObject*, void*); + class LIBSHIBOKEN_API BindingManager { public: @@ -50,6 +52,16 @@ class LIBSHIBOKEN_API BindingManager SbkObjectType* resolveType(void* cptr, SbkObjectType* type); std::set getAllPyObjects(); + + /** + * Calls the function \p visitor for each object registered on binding manager. + * \note As various C++ pointers can point to the same PyObject due to multiple inheritance + * a PyObject can be called more than one time for each PyObject. + * \param visitor function called for each object. + * \param data user data passed as second argument to the visitor function. + */ + void visitAllPyObjects(ObjectVisitor visitor, void* data); + private: ~BindingManager(); // disable copy From 6e11fa52dd2d02bb9e4a5cf6aeb1e25e62770ea3 Mon Sep 17 00:00:00 2001 From: Lauro Neto Date: Wed, 24 Nov 2010 11:45:23 -0300 Subject: [PATCH 150/564] Bump ApiExtractor dependency to 0.9.0 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f054633..1e87f621 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules/ ${CMAKE_MODULE_PATH}) find_package(Qt4 4.5.0) -find_package(ApiExtractor 0.8.2) +find_package(ApiExtractor 0.9.0) find_package(GeneratorRunner 0.6.3) find_package(PythonLibs) find_package(PythonInterpWithDebug) From 907842acf4baa9e520431157bf1b0293476d65c3 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 25 Nov 2010 15:22:13 -0200 Subject: [PATCH 151/564] Fix compilation errors on Windows. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Renato Araújo Luciano Wolf --- CMakeLists.txt | 1 + tests/libsample/samplenamespace.h | 9 ++++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e87f621..80eb5d38 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,7 @@ endif() if(WIN32 OR AVOID_PROTECTED_HACK) message(STATUS "Avoiding protected hack!") add_definitions("-DAVOID_PROTECTED_HACK") + set(AVOID_PROTECTED_HACK ON) else() message(STATUS "Using protected hack!") endif() diff --git a/tests/libsample/samplenamespace.h b/tests/libsample/samplenamespace.h index 7ac1ec19..d31e27ff 100644 --- a/tests/libsample/samplenamespace.h +++ b/tests/libsample/samplenamespace.h @@ -99,11 +99,10 @@ class SomeClass class DerivedFromNamespace : public SomeClass::SomeInnerClass::OkThisIsRecursiveEnough { public: -#ifndef _MSC_VER - //only cause namespace confusion - enum SampleNamespace { - }; -#endif + // FIXME Uncomment this when the fix for MSVC is available + // only to cause namespace confusion +// enum SampleNamespace { +// }; virtual OkThisIsRecursiveEnough* someVirtualMethod(OkThisIsRecursiveEnough* arg) { return arg; } inline OkThisIsRecursiveEnough* methodReturningTypeFromParentScope() { return 0; } }; From c4f7eab58b94fdbc934994aca0d0cfff9e8bbe13 Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Thu, 25 Nov 2010 16:49:04 -0300 Subject: [PATCH 152/564] Cast PySideSignal object to PyObject before calling Py_DECREF. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is done because the Py_DECREF macro from Python 2.5 doesn't cast the argument to "PyObject*" as 2.6 does. This is a problem for PySideSignal objects, for this struct is private, having only the forward declaration visible. Reviewed by Hugo Parente Reviewed by Renato Araújo --- generator/cppgenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index f4a4918e..11135c82 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -3042,7 +3042,7 @@ void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaC s << ", NULL);" << endl; s << INDENT << "PySide::Signal::addSignalToWrapper(&" + cpythonTypeName(metaClass) + ", \""; s << funcName << "\", signal_item);" << endl; - s << INDENT << "Py_DECREF(signal_item);" << endl; + s << INDENT << "Py_DECREF((PyObject*) signal_item);" << endl; } s << endl; } From 927a93926b792d83d5205ab7cbb086882c3a0688 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 25 Nov 2010 19:38:59 -0200 Subject: [PATCH 153/564] Fix shiboken version in doc generation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Renato Araújo Marcelo Lira --- doc/conf.py.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/conf.py.in b/doc/conf.py.in index 18d84e2a..e49e30fc 100644 --- a/doc/conf.py.in +++ b/doc/conf.py.in @@ -49,9 +49,9 @@ copyright = u'2009-2010, Nokia Corporation' # built documents. # # The short X.Y version. -version = '0.5' +version = '@shiboken_VERSION@' # The full version, including alpha/beta/rc tags. -release = '0.5.1' +release = '@shiboken_VERSION@' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. From 78aa3a49685e0d1775c0a2a7bf447c49db25f654 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Mon, 29 Nov 2010 14:37:39 -0200 Subject: [PATCH 154/564] Add function Shiboken::ObjectType::getUserData(SbjObjectTyoe*) --- libshiboken/basewrapper.cpp | 5 +++++ libshiboken/basewrapper.h | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 8f5acff8..eb01116c 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -560,6 +560,11 @@ void initPrivateData(SbkObjectType* self) memset(self->d, 0, sizeof(SbkObjectTypePrivate)); } +void* getTypeUserData(SbkObjectType* type) +{ + return type->d->user_data; +} + } // namespace ObjectType namespace Object diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 460f3159..30268dce 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -155,6 +155,11 @@ LIBSHIBOKEN_API MultipleInheritanceInitFunction getMultipleIheritanceFunction(Sb LIBSHIBOKEN_API void setDestructorFunction(SbkObjectType* self, ObjectDestructor func); LIBSHIBOKEN_API void initPrivateData(SbkObjectType* self); + +/** + * Get the user data previously setted by Shiboken::Object::setTypeUserData + */ +LIBSHIBOKEN_API void* getTypeUserData(SbkObjectType* type); } namespace Object { From 39383ee7bb8c489adf0d251685a9599c44360076 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Mon, 29 Nov 2010 14:43:53 -0200 Subject: [PATCH 155/564] Updated basewrapper.h docs. Reviewer: Luciano Wolf Marcelo Lira --- libshiboken/basewrapper.h | 68 ++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 8 deletions(-) diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 30268dce..1ddd40af 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -157,7 +157,7 @@ LIBSHIBOKEN_API void setDestructorFunction(SbkObjectType* self, ObjectDes LIBSHIBOKEN_API void initPrivateData(SbkObjectType* self); /** - * Get the user data previously setted by Shiboken::Object::setTypeUserData + * Get the user data previously set by Shiboken::Object::setTypeUserData */ LIBSHIBOKEN_API void* getTypeUserData(SbkObjectType* type); } @@ -168,25 +168,71 @@ namespace Object { * Returns true if the object is an instance of a type created by the Shiboken generator. */ LIBSHIBOKEN_API bool checkType(PyObject* pyObj); +/** + * Returns true if this object type is an instance of an user defined type derived from an Shiboken type. + * \see Shiboken::ObjectType::isUserType + */ LIBSHIBOKEN_API bool isUserType(PyObject* pyObj); - +/** + * Bind a C++ object to Python. + * \param instanceType equivalent Python type for the C++ object. + * \param hasOwnership if true, Python will try to delete the underlying C++ object when there's no more refs. + * \param isExactType if false, Shiboken will use some heuristics to detect the correct Python type of this C++ + * object, in any case you must provide \p instanceType, it'll be used as search starting point + * and as fallback. + * \param typeName If non-null, this will be used as helper to find the correct Python type for this object. + */ LIBSHIBOKEN_API PyObject* newObject(SbkObjectType* instanceType, void* cptr, bool hasOwnership = true, bool isExactType = false, const char* typeName = 0); +/** + * Changes the valid flag of a PyObject, invalid objects will raise an exception when someone tries to access it. + */ LIBSHIBOKEN_API void setValidCpp(SbkObject* pyObj, bool value); +/** + * Tells shiboken the Python object \p pyObj has a C++ wrapper used to intercept virtual method calls. + */ LIBSHIBOKEN_API void setHasCppWrapper(SbkObject* pyObj, bool value); +/** + * Return true if the Python object \p pyObj has a C++ wrapper used to intercept virtual method calls. + */ LIBSHIBOKEN_API bool hasCppWrapper(SbkObject* pyObj); +/** + * Return true if the Python is responsible for deleting the underlying C++ object. + */ LIBSHIBOKEN_API bool hasOwnership(SbkObject* pyObj); +/** + * Sets python as responsible to delete the underlying C++ object. + * \note You this overload only when the PyObject can be a sequence and you want to + * call this function for every item in the sequence. + * \see getOwnership(SbkObject*) + */ LIBSHIBOKEN_API void getOwnership(PyObject* pyObj); +/** + * Sets python as responsible to delete the underlying C++ object. + */ LIBSHIBOKEN_API void getOwnership(SbkObject* pyObj); + +/** + * Release the ownership, so Python will not delete the underlying C++ object. + * \note You this overload only when the PyObject can be a sequence and you want to + * call this function for every item in the sequence. + * \see releaseOwnership(SbkObject*) + */ LIBSHIBOKEN_API void releaseOwnership(PyObject* pyObj); +/** + * Release the ownership, so Python will not delete the underlying C++ object. + */ LIBSHIBOKEN_API void releaseOwnership(SbkObject* pyObj); +/** + * Returns true if the pyObj holds information about their parents. + */ LIBSHIBOKEN_API bool hasParentInfo(SbkObject* pyObj); /** @@ -206,7 +252,7 @@ LIBSHIBOKEN_API bool isValid(PyObject* wrapper); /** * Set the parent of \p child to \p parent. -* When an object dies, all their children, granchildren, etc, are tagged as invalid. +* When an object dies, all their children, grandchildren, etc, are tagged as invalid. * \param parent the parent object, if null, the child will have no parents. * \param child the child. */ @@ -219,7 +265,7 @@ LIBSHIBOKEN_API void setParent(PyObject* parent, PyObject* child); LIBSHIBOKEN_API void removeParent(SbkObject* child, bool giveOwnershipBack = true, bool keepReferenc = false); /** -* \internal This is an internal function called by SbkBaseWrapper_Dealloc, it's exported just for techinical reasons. +* \internal This is an internal function called by tp_dealloc, it's exported just for technical reasons. * \note Do not call this function inside your bindings. */ LIBSHIBOKEN_API void destroyParentInfo(SbkObject* obj, bool removeFromParent = true); @@ -230,7 +276,7 @@ LIBSHIBOKEN_API void destroyParentInfo(SbkObject* obj, bool removeFromPar LIBSHIBOKEN_API void invalidate(SbkObject* self); /** - * Help function can be used to invalida a sequence of object + * Help function can be used to invalidate a sequence of object **/ LIBSHIBOKEN_API void invalidate(PyObject* pyobj); @@ -245,9 +291,15 @@ LIBSHIBOKEN_API void makeValid(SbkObject* self); LIBSHIBOKEN_API void destroy(SbkObject* self); /** - * Get/Set Userdata in type class + * Set user data on type of \p wrapper. + * \param wrapper instance object, the user data will be set on his type + * \param userData the user data + * \param d_func a function used to delete the user data */ LIBSHIBOKEN_API void setTypeUserData(SbkObject* wrapper, void* userData, DeleteUserDataFunc d_func); +/** + * Get the user data previously set by Shiboken::Object::setTypeUserData + */ LIBSHIBOKEN_API void* getTypeUserData(SbkObject* wrapper); /** @@ -259,8 +311,8 @@ LIBSHIBOKEN_API void* getTypeUserData(SbkObject* wrapper); * No checking is done for any of the passed arguments, since it is meant to be used * by generated code it is supposed that the generator is correct. * \param self the wrapper instance that keeps references to other objects. - * \param key a key that identifies the C++ method signature and argument where the referredObject came from. - * \parem referredObject the object whose reference is used by the self object. + * \param key a key that identifies the C++ method signature and argument where the referred Object came from. + * \param referredObject the object whose reference is used by the self object. */ LIBSHIBOKEN_API void keepReference(SbkObject* self, const char* key, PyObject* referredObject, bool append = false); From 6d2e7d8a5cd7fea0507309107c8b306a44ef2ce0 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 1 Dec 2010 14:18:29 -0200 Subject: [PATCH 156/564] Remove const version of Converters to avoid hidding generator bugs. --- libshiboken/conversions.h | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index a49ec34d..ed7dcc01 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -172,16 +172,6 @@ struct Converter static inline T& toCpp(PyObject* pyobj) { return *Converter::toCpp(pyobj); } }; -template -struct Converter : Converter -{ - static inline PyObject* toPython(const T& cppobj) - { - T* cpy = CppObjectCopier::copy(cppobj); - return createWrapper(cpy); - } -}; - // Void pointer conversions. template<> struct Converter @@ -198,7 +188,6 @@ struct Converter } static void* toCpp(PyObject* pyobj) { return pyobj; } }; -template <> struct Converter : Converter {}; // Base converter meant to be inherited by converters for classes that could be // passed by value. @@ -298,7 +287,6 @@ struct Converter : ObjectTypeConverter { static inline PyObject* toCpp(PyObject* pyobj) { return pyobj; } }; -template <> struct Converter : Converter {}; // Primitive Conversions ------------------------------------------------------ template <> From d117950aa36d409140296d7efdfbbfc928722e04 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 1 Dec 2010 14:24:37 -0200 Subject: [PATCH 157/564] Remove objectDeleter function and use the well known Shiboken::callCppDestructor. --- libshiboken/typeresolver.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/libshiboken/typeresolver.h b/libshiboken/typeresolver.h index f959010f..6a3750c1 100644 --- a/libshiboken/typeresolver.h +++ b/libshiboken/typeresolver.h @@ -47,12 +47,6 @@ inline void* pythonToObjectType(PyObject* pyobj, void** data, bool) return *data; } -template -inline void objectDeleter(void* data) -{ - delete reinterpret_cast(data); -} - template inline PyObject* objectTypeToPython(void* cptr) { @@ -84,7 +78,7 @@ class LIBSHIBOKEN_API TypeResolver template static TypeResolver* createValueTypeResolver(const char* typeName) { - return new TypeResolver(typeName, &Shiboken::Converter::toPython, &pythonToValueType, SbkType(), &objectDeleter); + return new TypeResolver(typeName, &Shiboken::Converter::toPython, &pythonToValueType, SbkType(), &callCppDestructor); } template From aebf1341686e1a694a5ad9b24e384ee494683af8 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 1 Dec 2010 14:27:39 -0200 Subject: [PATCH 158/564] Remove SbkTypeInfo and CppObjectCopier structs, they aren't needed after the fix on qt_metacall. --- generator/headergenerator.cpp | 13 ------------ generator/headergenerator.h | 1 - libshiboken/conversions.h | 37 +---------------------------------- libshiboken/typeresolver.cpp | 4 ++-- libshiboken/typeresolver.h | 17 ++++++---------- 5 files changed, 9 insertions(+), 63 deletions(-) diff --git a/generator/headergenerator.cpp b/generator/headergenerator.cpp index 3e242cc1..76206d32 100644 --- a/generator/headergenerator.cpp +++ b/generator/headergenerator.cpp @@ -360,7 +360,6 @@ void HeaderGenerator::finishGeneration() if (!metaClass->isNamespace()) { writeSbkTypeFunction(typeFunctions, metaClass); - writeSbkCopyCppObjectFunction(convDecl, metaClass); writeTypeConverterDecl(convDecl, classType); writeTypeConverterImpl(convImpl, classType); convDecl << endl; @@ -505,18 +504,6 @@ void HeaderGenerator::writeSbkTypeFunction(QTextStream& s, const AbstractMetaCla << "{ return reinterpret_cast(" << cpythonTypeNameExt(cppClass->typeEntry()) << "); }\n"; } -void HeaderGenerator::writeSbkCopyCppObjectFunction(QTextStream& s, const AbstractMetaClass* metaClass) -{ - if (!metaClass->typeEntry()->isValue() || !shouldGenerateCppWrapper(metaClass)) - return; - QString className = metaClass->qualifiedCppName(); - s << "template <>" << endl; - s << "struct SbkTypeInfo<" << className << " >" << endl; - s << '{' << endl; - s << INDENT << "static const bool isCppWrapper = true;" << endl; - s << "};" << endl; -} - void HeaderGenerator::writeTypeConverterImpl(QTextStream& s, const TypeEntry* type) { if (type->hasNativeConversionRule()) diff --git a/generator/headergenerator.h b/generator/headergenerator.h index 96d63c64..d7502a9e 100644 --- a/generator/headergenerator.h +++ b/generator/headergenerator.h @@ -47,7 +47,6 @@ class HeaderGenerator : public ShibokenGenerator void writeTypeConverterDecl(QTextStream& s, const TypeEntry* type); void writeSbkTypeFunction(QTextStream& s, const AbstractMetaEnum* cppEnum); void writeSbkTypeFunction(QTextStream& s, const AbstractMetaClass* cppClass); - void writeSbkCopyCppObjectFunction(QTextStream& s, const AbstractMetaClass* metaClass); void writeTypeIndexDefineLine(QTextStream& s, const TypeEntry* typeEntry, int& idx); void writeTypeIndexDefine(QTextStream& s, const AbstractMetaClass* metaClass, int& idx); void writeTypeConverterImpl(QTextStream& s, const TypeEntry* type); diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index ed7dcc01..8b312dfe 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -69,41 +69,6 @@ template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } template<> inline PyTypeObject* SbkType() { return &PyInt_Type; } -template -struct SbkTypeInfo { - static const bool isCppWrapper = false; -}; - -/** - * This struct template is used to copy a C++ object using the proper - * constructor, which could be the same type as used on the wrapped library - * or a C++ wrapper type provided by the binding. - */ -template ::isCppWrapper> -struct CppObjectCopier -{ - static inline T* copy(const T& obj); -}; - -template -struct CppObjectCopier -{ - static inline T* copy(const T& obj) - { - return new T(obj); - } -}; - -template -struct CppObjectCopier -{ - static inline T* copy(const T& obj) - { - return reinterpret_cast(ObjectType::copy(reinterpret_cast(SbkType()), &obj)); - } -}; - - /** * Convenience template to create wrappers using the proper Python type for a given C++ class instance. */ @@ -152,7 +117,7 @@ struct Converter if (PyObject_TypeCheck(pyobj, SbkType())) return (T*) Object::cppPointer(reinterpret_cast(pyobj), SbkType()); else if (Converter::isConvertible(pyobj)) - return CppObjectCopier::copy(Converter::toCpp(pyobj)); + return new T(Converter::toCpp(pyobj)); else if (pyobj == Py_None) return 0; diff --git a/libshiboken/typeresolver.cpp b/libshiboken/typeresolver.cpp index 3d0cb11a..8d3ce7a9 100644 --- a/libshiboken/typeresolver.cpp +++ b/libshiboken/typeresolver.cpp @@ -97,9 +97,9 @@ const char* TypeResolver::typeName() const return m_d->typeName; } -void* TypeResolver::toCpp(PyObject* pyObj, void** place, bool alloc) +void TypeResolver::toCpp(PyObject* pyObj, void** place) { - return m_d->pythonToCpp(pyObj, place, alloc); + m_d->pythonToCpp(pyObj, place); } void TypeResolver::deleteObject(void* object) diff --git a/libshiboken/typeresolver.h b/libshiboken/typeresolver.h index 6a3750c1..d53d313f 100644 --- a/libshiboken/typeresolver.h +++ b/libshiboken/typeresolver.h @@ -31,20 +31,15 @@ namespace Shiboken /* To C++ convertion functions. */ template -inline void* pythonToValueType(PyObject* pyobj, void** data, bool alloc) +inline void pythonToValueType(PyObject* pyobj, void** data) { - if (alloc) - *data = Shiboken::CppObjectCopier::copy(Shiboken::Converter::toCpp(pyobj)); - - *reinterpret_cast< T*>(*data) = Shiboken::Converter::toCpp(pyobj); - return *data; + *reinterpret_cast(*data) = Shiboken::Converter::toCpp(pyobj); } template -inline void* pythonToObjectType(PyObject* pyobj, void** data, bool) +inline void pythonToObjectType(PyObject* pyobj, void** data) { - *data = Shiboken::Converter::toCpp(pyobj); - return *data; + *reinterpret_cast(*data) = Shiboken::Converter::toCpp(pyobj); } template @@ -70,7 +65,7 @@ class LIBSHIBOKEN_API TypeResolver }; typedef PyObject* (*CppToPythonFunc)(void*); - typedef void* (*PythonToCppFunc)(PyObject*, void**, bool); + typedef void (*PythonToCppFunc)(PyObject*, void**); typedef void (*DeleteObjectFunc)(void*); ~TypeResolver(); @@ -92,7 +87,7 @@ class LIBSHIBOKEN_API TypeResolver const char* typeName() const; PyObject* toPython(void* cppObj); - void* toCpp(PyObject* pyObj, void** place, bool alloc=false); + void toCpp(PyObject* pyObj, void** place); void deleteObject(void* object); PyTypeObject* pythonType(); From 4954a2e8c95df27168b65519a8b61ce30b8ab0d6 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 1 Dec 2010 18:05:33 -0200 Subject: [PATCH 159/564] Removed useless stuff from TypeResolver. --- libshiboken/typeresolver.cpp | 41 ++++++++++++------------------------ libshiboken/typeresolver.h | 10 ++++----- 2 files changed, 17 insertions(+), 34 deletions(-) diff --git a/libshiboken/typeresolver.cpp b/libshiboken/typeresolver.cpp index 8d3ce7a9..e776b49f 100644 --- a/libshiboken/typeresolver.cpp +++ b/libshiboken/typeresolver.cpp @@ -33,10 +33,8 @@ static TypeResolverMap typeResolverMap; struct TypeResolver::TypeResolverPrivate { - const char* typeName; // maybe this is not needed anymore CppToPythonFunc cppToPython; PythonToCppFunc pythonToCpp; - DeleteObjectFunc deleteObject; PyTypeObject* pyType; }; @@ -55,25 +53,23 @@ void Shiboken::initTypeResolver() std::atexit(deinitTypeResolver); } -static void registerTypeResolver(TypeResolver* resolver) +TypeResolver::TypeResolver() : m_d(new TypeResolverPrivate) { - TypeResolver*& v = typeResolverMap[resolver->typeName()]; - if (!v) - v = resolver; - else - delete resolver; // Discard type resolvers already registered } -TypeResolver::TypeResolver(const char* typeName, TypeResolver::CppToPythonFunc cppToPy, TypeResolver::PythonToCppFunc pyToCpp, PyTypeObject* pyType, TypeResolver::DeleteObjectFunc deleter) +TypeResolver* TypeResolver::createTypeResolver(const char* typeName, + CppToPythonFunc cppToPy, + PythonToCppFunc pyToCpp, + PyTypeObject* pyType) { - m_d = new TypeResolverPrivate; - m_d->typeName = typeName; - m_d->cppToPython = cppToPy; - m_d->pythonToCpp = pyToCpp; - m_d->deleteObject = deleter; - m_d->pyType = pyType; - - registerTypeResolver(this); + TypeResolver*& tr = typeResolverMap[typeName]; + if (!tr) { + tr = new TypeResolver; + tr->m_d->cppToPython = cppToPy; + tr->m_d->pythonToCpp = pyToCpp; + tr->m_d->pyType = pyType; + } + return tr; } TypeResolver::~TypeResolver() @@ -92,22 +88,11 @@ TypeResolver* TypeResolver::get(const char* typeName) } } -const char* TypeResolver::typeName() const -{ - return m_d->typeName; -} - void TypeResolver::toCpp(PyObject* pyObj, void** place) { m_d->pythonToCpp(pyObj, place); } -void TypeResolver::deleteObject(void* object) -{ - if (m_d->deleteObject) - m_d->deleteObject(object); -} - PyObject* TypeResolver::toPython(void* cppObj) { return m_d->cppToPython(cppObj); diff --git a/libshiboken/typeresolver.h b/libshiboken/typeresolver.h index d53d313f..cdd379bc 100644 --- a/libshiboken/typeresolver.h +++ b/libshiboken/typeresolver.h @@ -66,40 +66,38 @@ class LIBSHIBOKEN_API TypeResolver typedef PyObject* (*CppToPythonFunc)(void*); typedef void (*PythonToCppFunc)(PyObject*, void**); - typedef void (*DeleteObjectFunc)(void*); ~TypeResolver(); template static TypeResolver* createValueTypeResolver(const char* typeName) { - return new TypeResolver(typeName, &Shiboken::Converter::toPython, &pythonToValueType, SbkType(), &callCppDestructor); + return createTypeResolver(typeName, &Shiboken::Converter::toPython, &pythonToValueType, SbkType()); } template static TypeResolver* createObjectTypeResolver(const char* typeName) { - return new TypeResolver(typeName, &objectTypeToPython, &pythonToObjectType, SbkType()); + return createTypeResolver(typeName, &objectTypeToPython, &pythonToObjectType, SbkType()); } static Type getType(const char* name); static TypeResolver* get(const char* typeName); - const char* typeName() const; PyObject* toPython(void* cppObj); void toCpp(PyObject* pyObj, void** place); - void deleteObject(void* object); PyTypeObject* pythonType(); private: struct TypeResolverPrivate; TypeResolverPrivate* m_d; + TypeResolver(); // disable object copy TypeResolver(const TypeResolver&); TypeResolver& operator=(const TypeResolver&); - TypeResolver(const char* typeName, CppToPythonFunc cppToPy, PythonToCppFunc pyToCpp, PyTypeObject* pyType, DeleteObjectFunc deleter = 0); + static TypeResolver* createTypeResolver(const char* typeName, CppToPythonFunc cppToPy, PythonToCppFunc pyToCpp, PyTypeObject* pyType); }; } From a5146ad246af19703671451451564e613e509463 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 1 Dec 2010 21:16:40 -0200 Subject: [PATCH 160/564] Remove cpp object copier as it was used by anyone and nobody missed him. Reviewer: Luciano Wolf Lauro Moura --- generator/cppgenerator.cpp | 16 ---------------- generator/cppgenerator.h | 1 - libshiboken/basewrapper.cpp | 12 ------------ libshiboken/basewrapper.h | 7 ------- libshiboken/basewrapper_p.h | 1 - 5 files changed, 37 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 11135c82..199489dc 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -410,7 +410,6 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl if (!metaClass->typeEntry()->hashFunction().isEmpty()) writeHashFunction(s, metaClass); - writeObjCopierFunction(s, metaClass); writeClassDefinition(s, metaClass); s << endl; @@ -3265,10 +3264,6 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m s << INDENT << "Shiboken::ObjectType::setDestructorFunction(&" << cpythonTypeName(metaClass) << ", &Shiboken::callCppDestructor<" << dtorClassName << " >);" << endl; } - // Fill copy function - if (metaClass->typeEntry()->isValue() && shouldGenerateCppWrapper(metaClass)) - s << INDENT << "Shiboken::ObjectType::setCopyFunction(&" << cpythonTypeName(metaClass) << ", &" << cpythonBaseName(metaClass) + "_ObjCopierFunc);" << endl; - s << INDENT << "if (PyType_Ready((PyTypeObject*)&" << pyTypeName << ") < 0)" << endl; s << INDENT << INDENT << "return;" << endl << endl; @@ -3869,17 +3864,6 @@ void CppGenerator::writeHashFunction(QTextStream& s, const AbstractMetaClass* me s << '}' << endl << endl; } -void CppGenerator::writeObjCopierFunction(QTextStream& s, const AbstractMetaClass* metaClass) -{ - if (!(metaClass->typeEntry()->isValue() && shouldGenerateCppWrapper(metaClass))) - return; - s << "static void* " << cpythonBaseName(metaClass) << "_ObjCopierFunc(const void* ptr)"; - s << '{' << endl; - s << INDENT << "return new " << wrapperName(metaClass) << "(*reinterpret_castqualifiedCppName() << "*>(ptr));\n"; - s << '}' << endl << endl; - -} - void CppGenerator::writeStdListWrapperMethods(QTextStream& s, const AbstractMetaClass* metaClass) { //len diff --git a/generator/cppgenerator.h b/generator/cppgenerator.h index 4374eb5e..6e064dd4 100644 --- a/generator/cppgenerator.h +++ b/generator/cppgenerator.h @@ -187,7 +187,6 @@ class CppGenerator : public ShibokenGenerator bool shouldGenerateGetSetList(const AbstractMetaClass* metaClass); void writeHashFunction(QTextStream& s, const AbstractMetaClass* metaClass); - void writeObjCopierFunction(QTextStream& s, const AbstractMetaClass* metaClass); // Write default implementations for sequence protocol void writeStdListWrapperMethods(QTextStream& s, const AbstractMetaClass* metaClass); diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index eb01116c..09c47bda 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -218,7 +218,6 @@ PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* k d->ext_isconvertible = parentType->ext_isconvertible; d->ext_tocpp = parentType->ext_tocpp; d->type_discovery = parentType->type_discovery; - d->obj_copier = parentType->obj_copier; d->cpp_dtor = parentType->cpp_dtor; d->is_multicpp = 0; } else { @@ -228,7 +227,6 @@ PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* k d->ext_isconvertible = 0; d->ext_tocpp = 0; d->type_discovery = 0; - d->obj_copier = 0; d->cpp_dtor = 0; d->is_multicpp = 1; } @@ -460,16 +458,6 @@ bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType) return true; } -void* copy(SbkObjectType* self, const void* obj) -{ - return self->d->obj_copier(obj); -} - -void setCopyFunction(SbkObjectType* self, ObjectCopierFunction func) -{ - self->d->obj_copier = func; -} - bool hasExternalCppConversions(SbkObjectType* self) { return self->d->ext_tocpp; diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 1ddd40af..0f836079 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -62,7 +62,6 @@ typedef int* (*MultipleInheritanceInitFunction)(const void*); * The implementation of this function is auto generated by the generator and you don't need to care about it. */ typedef void* (*SpecialCastFunction)(void*, SbkObjectType*); -typedef void* (*ObjectCopierFunction)(const void*); typedef SbkObjectType* (*TypeDiscoveryFunc)(void*, SbkObjectType*); typedef void* (*ExtendedToCppFunc)(PyObject*); @@ -126,12 +125,6 @@ LIBSHIBOKEN_API bool isUserType(PyTypeObject* pyObj); */ LIBSHIBOKEN_API bool canCallConstructor(PyTypeObject* myType, PyTypeObject* ctorType); -/** - * Call copy function for the object type - **/ -LIBSHIBOKEN_API void* copy(SbkObjectType* self, const void* obj); -LIBSHIBOKEN_API void setCopyFunction(SbkObjectType* self, ObjectCopierFunction func); - LIBSHIBOKEN_API void setExternalCppConversionFunction(SbkObjectType* self, ExtendedToCppFunc func); LIBSHIBOKEN_API void setExternalIsConvertibleFunction(SbkObjectType* self, ExtendedIsConvertibleFunc func); LIBSHIBOKEN_API bool hasExternalCppConversions(SbkObjectType* self); diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h index b90aaa45..05208848 100644 --- a/libshiboken/basewrapper_p.h +++ b/libshiboken/basewrapper_p.h @@ -89,7 +89,6 @@ struct SbkObjectTypePrivate /// Special cast function, null if this class doesn't have multiple inheritance. SpecialCastFunction mi_specialcast; TypeDiscoveryFunc type_discovery; - ObjectCopierFunction obj_copier; /// Extended "isConvertible" function to be used when a conversion operator is defined in another module. ExtendedIsConvertibleFunc ext_isconvertible; /// Extended "toCpp" function to be used when a conversion operator is defined in another module. From 07f1fe9dc97e05247043b3e579d94d323a2a48dc Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 3 Dec 2010 16:53:26 -0200 Subject: [PATCH 161/564] Add subtype init hook. The hook is invoked every time the user creates a sub-type inherited from a Shiboken based type. --- libshiboken/basewrapper.cpp | 22 ++++++++++++++++++++-- libshiboken/basewrapper.h | 14 +++++++++++++- libshiboken/basewrapper_p.h | 1 + 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 09c47bda..b3fc3801 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -238,6 +238,13 @@ PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* k d->d_func = 0; d->is_user_type = 1; newType->d = d; + + std::list::const_iterator it = bases.begin(); + for (; it != bases.end(); ++it) { + if ((*it)->d->subtype_init) + (*it)->d->subtype_init(newType, args, kwds); + } + return reinterpret_cast(newType); } @@ -548,9 +555,20 @@ void initPrivateData(SbkObjectType* self) memset(self->d, 0, sizeof(SbkObjectTypePrivate)); } -void* getTypeUserData(SbkObjectType* type) +void setSubTypeInitHook(SbkObjectType* self, SubTypeInitHook func) +{ + self->d->subtype_init = func; +} + +void* getTypeUserData(SbkObjectType* self) +{ + return self->d->user_data; +} + +void setTypeUserData(SbkObjectType* self, void* userData, DeleteUserDataFunc d_func) { - return type->d->user_data; + self->d->user_data = userData; + self->d->d_func = d_func; } } // namespace ObjectType diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 0f836079..46bc641d 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -72,6 +72,8 @@ typedef void (*DeleteUserDataFunc)(void*); typedef void (*ObjectDestructor)(void*); +typedef void (*SubTypeInitHook)(SbkObjectType*, PyObject*, PyObject*); + extern LIBSHIBOKEN_API PyTypeObject SbkObjectType_Type; extern LIBSHIBOKEN_API SbkObjectType SbkObject_Type; @@ -149,10 +151,20 @@ LIBSHIBOKEN_API void setDestructorFunction(SbkObjectType* self, ObjectDes LIBSHIBOKEN_API void initPrivateData(SbkObjectType* self); +/** + * Set the subtype init hook for a type. + * + * This hook will be invoked every time the user creates a sub-type inherited from a Shiboken based type. + * The hook gets 3 params, they are: The new type being created, args and kwds. The last two are the very + * same got from tp_new. + */ +LIBSHIBOKEN_API void setSubTypeInitHook(SbkObjectType* self, SubTypeInitHook func); + /** * Get the user data previously set by Shiboken::Object::setTypeUserData */ -LIBSHIBOKEN_API void* getTypeUserData(SbkObjectType* type); +LIBSHIBOKEN_API void* getTypeUserData(SbkObjectType* self); +LIBSHIBOKEN_API void setTypeUserData(SbkObjectType* self, void* userData, DeleteUserDataFunc d_func); } namespace Object { diff --git a/libshiboken/basewrapper_p.h b/libshiboken/basewrapper_p.h index 05208848..f4ab6e65 100644 --- a/libshiboken/basewrapper_p.h +++ b/libshiboken/basewrapper_p.h @@ -104,6 +104,7 @@ struct SbkObjectTypePrivate /// Type user data void *user_data; DeleteUserDataFunc d_func; + void (*subtype_init)(SbkObjectType*, PyObject*, PyObject*); }; From 53a4a73c516bbeec546cb20234dad6bd9912fdaa Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 3 Dec 2010 16:55:09 -0200 Subject: [PATCH 162/564] Write a simpler code to deal with dynamic QMetaObjects. Reviewer: Luciano Wolf Marcelo Lira --- generator/cppgenerator.cpp | 39 ++++++++++------------------------- generator/headergenerator.cpp | 2 -- 2 files changed, 11 insertions(+), 30 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 199489dc..b95d1cf2 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -173,7 +173,6 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl if (usePySideExtensions()) { if (metaClass->isQObject()) { s << "#include " << endl; - s << "#include " << endl; s << "#include " << endl; } } @@ -452,9 +451,6 @@ void CppGenerator::writeConstructorNative(QTextStream& s, const AbstractMetaFunc OriginalTypeDescription | SkipDefaultValues); s << " : "; writeFunctionCall(s, func); - if (usePySideExtensions() && func->ownerClass()->isQObject()) - s << ", m_metaObject(0)"; - s << " {" << endl; const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last(); writeCodeSnips(s, func->injectedCodeSnips(), CodeSnip::Beginning, TypeSystem::NativeCode, func, lastArg); @@ -779,31 +775,13 @@ void CppGenerator::writeMetaObjectMethod(QTextStream& s, const AbstractMetaClass { Indentation indentation(INDENT); QString wrapperClassName = wrapperName(metaClass); - QString prefix = wrapperClassName + "::"; - s << "const QMetaObject* " << wrapperClassName << "::metaObject() const\n{\n"; - s << INDENT << "if (!m_metaObject) {\n"; - { - Indentation indentation(INDENT); - s << INDENT << "SbkObject* pySelf = Shiboken::BindingManager::instance().retrieveWrapper(this);\n" - << INDENT << "void* typeData = Shiboken::Object::getTypeUserData(pySelf);" << endl - << INDENT << "if (!typeData) {" << endl; - { - Indentation indentation2(INDENT); - s << INDENT << "m_metaObject = PySide::DynamicQMetaObject::createBasedOn((PyObject*)pySelf, pySelf->ob_type, &" - << metaClass->qualifiedCppName() << "::staticMetaObject);" << endl - << INDENT << "Shiboken::Object::setTypeUserData(pySelf, m_metaObject, Shiboken::callCppDestructor);" << endl; - } - s << INDENT << "} else {" << endl; - { - Indentation indentation2(INDENT); - s << INDENT << "m_metaObject = reinterpret_cast(typeData);" << endl; - } - s << INDENT << "}" << endl; - } - s << INDENT << "}" << endl; - s << INDENT << "return m_metaObject;\n"; - s << "}\n\n"; + s << "const QMetaObject* " << wrapperClassName << "::metaObject() const" << endl; + s << '{' << endl; + s << INDENT << "SbkObject* pySelf = Shiboken::BindingManager::instance().retrieveWrapper(this);" << endl; + s << INDENT << "return reinterpret_cast(Shiboken::Object::getTypeUserData(pySelf));" << endl; + s << '}' << endl << endl; + // qt_metacall function s << "int " << wrapperClassName << "::qt_metacall(QMetaObject::Call call, int id, void** args)\n"; s << "{\n"; s << INDENT << "int result = " << metaClass->qualifiedCppName() << "::qt_metacall(call, id, args);\n"; @@ -3214,6 +3192,11 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m // alloc private data s << INDENT << "Shiboken::ObjectType::initPrivateData(&" << cpythonTypeName(metaClass->typeEntry()) << ");" << endl; + if (usePySideExtensions() && metaClass->isQObject()) { + s << INDENT << "Shiboken::ObjectType::setSubTypeInitHook(&" << cpythonTypeName(metaClass->typeEntry()) << ", &PySide::initQObjectSubType);" << endl; + s << INDENT << "PySide::initDynamicMetaObject(&" << cpythonTypeName(metaClass->typeEntry()) << ", &" << metaClass->qualifiedCppName() << "::staticMetaObject);"; + } + // class inject-code target/beginning if (!metaClass->typeEntry()->codeSnips().isEmpty()) { writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), CodeSnip::Beginning, TypeSystem::TargetLangCode, 0, 0, metaClass); diff --git a/generator/headergenerator.cpp b/generator/headergenerator.cpp index 76206d32..7a49a8c4 100644 --- a/generator/headergenerator.cpp +++ b/generator/headergenerator.cpp @@ -123,8 +123,6 @@ void HeaderGenerator::generateClass(QTextStream& s, const AbstractMetaClass* met if (usePySideExtensions() && metaClass->isQObject()) { s << "public:\n"; s << INDENT << "virtual int qt_metacall(QMetaObject::Call call, int id, void** args);\n"; - s << "private:\n"; - s << INDENT << "mutable PySide::DynamicQMetaObject* m_metaObject;\n"; } #ifdef AVOID_PROTECTED_HACK From ee4f78f615160b65b2d8f3f11a6735fd7da9f0fc Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Mon, 6 Dec 2010 13:52:44 -0300 Subject: [PATCH 163/564] Generator now writes the proper variable name on C++ constructor calls. When a conversion rule is provided for a constructor argument the C++ constructor, for which the conversion rule doesn't apply, is generated with wrong argument names. This commit solves this. --- generator/shibokengenerator.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/generator/shibokengenerator.cpp b/generator/shibokengenerator.cpp index b064573d..8be8964e 100644 --- a/generator/shibokengenerator.cpp +++ b/generator/shibokengenerator.cpp @@ -1013,7 +1013,8 @@ void ShibokenGenerator::writeArgumentNames(QTextStream &s, if (((options & Generator::VirtualCall) == 0) && (!func->conversionRule(TypeSystem::NativeCode, arguments.at(j)->argumentIndex() + 1).isEmpty() || - !func->conversionRule(TypeSystem::TargetLangCode, arguments.at(j)->argumentIndex() + 1).isEmpty()) + !func->conversionRule(TypeSystem::TargetLangCode, arguments.at(j)->argumentIndex() + 1).isEmpty()) && + !func->isConstructor() ) s << "_out"; From ff592945dbf0cb990ca13d60f480eeead7e34a99 Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Mon, 6 Dec 2010 14:30:33 -0300 Subject: [PATCH 164/564] Test case for proper generation of constructor altered by conversion-rule tag. Reviewed by Hugo Parente Reviewed by Luciano Wolf --- tests/libsample/ctorconvrule.h | 38 +++++++++++++++++++ tests/samplebinding/CMakeLists.txt | 1 + tests/samplebinding/ctorconvrule_test.py | 45 +++++++++++++++++++++++ tests/samplebinding/global.h | 1 + tests/samplebinding/typesystem_sample.xml | 13 +++++++ 5 files changed, 98 insertions(+) create mode 100644 tests/libsample/ctorconvrule.h create mode 100644 tests/samplebinding/ctorconvrule_test.py diff --git a/tests/libsample/ctorconvrule.h b/tests/libsample/ctorconvrule.h new file mode 100644 index 00000000..681bd78f --- /dev/null +++ b/tests/libsample/ctorconvrule.h @@ -0,0 +1,38 @@ +/* + * This file is part of the Shiboken Python Binding Generator project. + * + * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef CTORCONVRULE_H +#define CTORCONVRULE_H + +#include "libsamplemacros.h" + +class CtorConvRule +{ +public: + explicit CtorConvRule(long value) : m_value(value) {} + virtual void dummyVirtualMethod() {} + long value() { return m_value; } +private: + long m_value; +}; + +#endif diff --git a/tests/samplebinding/CMakeLists.txt b/tests/samplebinding/CMakeLists.txt index a0f68c54..5e3498cb 100644 --- a/tests/samplebinding/CMakeLists.txt +++ b/tests/samplebinding/CMakeLists.txt @@ -16,6 +16,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/base6_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/blackbox_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/bucket_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/collector_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/ctorconvrule_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/sbkdate_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/derived_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/derived_someinnerclass_wrapper.cpp diff --git a/tests/samplebinding/ctorconvrule_test.py b/tests/samplebinding/ctorconvrule_test.py new file mode 100644 index 00000000..7d8747f4 --- /dev/null +++ b/tests/samplebinding/ctorconvrule_test.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +# -*- coding: utf-8 -*- +# +# This file is part of the Shiboken Python Bindings Generator project. +# +# Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +# +# Contact: PySide team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# version 2.1 as published by the Free Software Foundation. Please +# review the following information to ensure the GNU Lesser General +# Public License version 2.1 requirements will be met: +# http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +# # +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +'''Test cases for proper generation of constructor altered by conversion-rule tag.''' + +import unittest + +from sample import CtorConvRule + +class TestCtorConvRule(unittest.TestCase): + '''Simple test case for CtorConvRule''' + + def testCtorConvRule(self): + '''Test CtorConvRule argument modification through conversion-rule tag.''' + value = 123 + obj = CtorConvRule(value) + self.assertEqual(obj.value(), value + 1) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/samplebinding/global.h b/tests/samplebinding/global.h index 8fae4ddf..f85ee69b 100644 --- a/tests/samplebinding/global.h +++ b/tests/samplebinding/global.h @@ -3,6 +3,7 @@ #include "bucket.h" #include "collector.h" #include "complex.h" +#include "ctorconvrule.h" #include "sbkdate.h" #include "derived.h" #include "echo.h" diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index fb133b51..f0a78e1e 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -1216,6 +1216,19 @@ + + + + + + // Does nothing really, just test the code generation + // of constructors whose arguments where + long %out = PyInt_AS_LONG(%PYARG_1) + 1; + + + + + %PYARG_0 = PyString_FromString(""); From 5b59c65a0f39198c4613400b9a49000b7d2315de Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 8 Dec 2010 16:46:50 -0200 Subject: [PATCH 165/564] Added another overload for makeTuple, this time with just one argument. Reviewer: Marcelo Lira Luciano Wolf --- libshiboken/helper.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/libshiboken/helper.h b/libshiboken/helper.h index 9aa06ffe..52b41270 100644 --- a/libshiboken/helper.h +++ b/libshiboken/helper.h @@ -1,7 +1,7 @@ /* * This file is part of the Shiboken Python Bindings Generator project. * - * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). + * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * @@ -31,6 +31,12 @@ namespace Shiboken { +template +inline PyObject* makeTuple(const A& a) +{ + return PyTuple_Pack(1, AutoDecRef(Converter::toPython(a)).object()); +} + template inline PyObject* makeTuple(const A& a, const B& b) { From 33537a0e9b0c3fc362032dec1820f08d248bed77 Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Thu, 9 Dec 2010 15:56:26 -0300 Subject: [PATCH 166/564] Code generated for Qt's signals wrapping now deal with arguments with default values. For instance, the "QAbstractButton::clicked(bool checked = false)" signal, can be connected using the two signatures "clicked()" and "clicked(bool)". Using button.clicked.connect(callback_function) could cause the binding to connect to "clicked(bool)", instead of "clicked()", leaving the user unaware of it. Reviewed by Hugo Parente Reviewed by Luciano Wolf --- generator/cppgenerator.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index b95d1cf2..0c99b09c 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2991,6 +2991,13 @@ void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaC QString cppSignature = QMetaObject::normalizedType(qPrintable(type->cppSignature())); QString originalSignature = QMetaObject::normalizedType(qPrintable(type->originalTypeDescription())); + if (!a->defaultValueExpression().isEmpty()) { + QString sig = QMetaObject::normalizedSignature(signature.toAscii()); + if (sig.isEmpty()) + sig = "void"; + signatures[cppSignal->name()].append(sig); + } + if ((cppSignature != originalSignature) && !knowTypes.contains(originalSignature)) { knowTypes << originalSignature; s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver<" From fb90a3df97b53f3ef4878d8beb719d4aa7b0c6cb Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 9 Dec 2010 19:37:41 -0200 Subject: [PATCH 167/564] Fix bug#500 - "If an instance of QPrintDialog is created a deadlock happens on shutdown." Reviewer: Lauro Mora Marcelo Lira --- libshiboken/basewrapper.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index b3fc3801..96a0f6f8 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -30,6 +30,7 @@ #include #include #include +#include "threadstatesaver.h" extern "C" { @@ -159,6 +160,8 @@ void SbkDeallocWrapper(PyObject* pyObj) if (sbkObj->weakreflist) PyObject_ClearWeakRefs(pyObj); + Shiboken::ThreadStateSaver threadSaver; + threadSaver.save(); // If I have ownership and is valid delete C++ pointer if (sbkObj->d->hasOwnership && sbkObj->d->validCppObject) { SbkObjectType* sbkType = reinterpret_cast(pyObj->ob_type); @@ -169,7 +172,7 @@ void SbkDeallocWrapper(PyObject* pyObj) sbkType->d->cpp_dtor(sbkObj->d->cptr[0]); } } - + threadSaver.restore(); Shiboken::Object::deallocData(sbkObj, !sbkObj->d->containsCppWrapper); } From 701b31ef3ddae7c43380d1513f9938f70f46eb7e Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Mon, 13 Dec 2010 15:22:10 -0200 Subject: [PATCH 168/564] Revert "Fix bug#500 - "If an instance of QPrintDialog is created a deadlock happens on shutdown."" This reverts commit fb90a3df97b53f3ef4878d8beb719d4aa7b0c6cb. --- libshiboken/basewrapper.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 96a0f6f8..b3fc3801 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -30,7 +30,6 @@ #include #include #include -#include "threadstatesaver.h" extern "C" { @@ -160,8 +159,6 @@ void SbkDeallocWrapper(PyObject* pyObj) if (sbkObj->weakreflist) PyObject_ClearWeakRefs(pyObj); - Shiboken::ThreadStateSaver threadSaver; - threadSaver.save(); // If I have ownership and is valid delete C++ pointer if (sbkObj->d->hasOwnership && sbkObj->d->validCppObject) { SbkObjectType* sbkType = reinterpret_cast(pyObj->ob_type); @@ -172,7 +169,7 @@ void SbkDeallocWrapper(PyObject* pyObj) sbkType->d->cpp_dtor(sbkObj->d->cptr[0]); } } - threadSaver.restore(); + Shiboken::Object::deallocData(sbkObj, !sbkObj->d->containsCppWrapper); } From 66bb59f9be9f7f38af48b1c4dc1108017c06ef72 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Mon, 13 Dec 2010 18:36:53 -0200 Subject: [PATCH 169/564] Fix bug#513 - "Hardcoded bool return type for operator overloads" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Renato Araújo Luciano Wolf --- generator/cppgenerator.cpp | 34 ++---- libshiboken/conversions.h | 5 +- tests/libsample/CMakeLists.txt | 1 + tests/libsample/expression.cpp | 127 ++++++++++++++++++++++ tests/libsample/expression.h | 58 ++++++++++ tests/samplebinding/CMakeLists.txt | 1 + tests/samplebinding/global.h | 1 + tests/samplebinding/reference_test.py | 2 +- tests/samplebinding/richcompare_test.py | 41 +++++++ tests/samplebinding/typesystem_sample.xml | 2 + 10 files changed, 245 insertions(+), 27 deletions(-) create mode 100644 tests/libsample/expression.cpp create mode 100644 tests/libsample/expression.h create mode 100644 tests/samplebinding/richcompare_test.py diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 0c99b09c..55747d37 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -29,7 +29,7 @@ #include #include -// utiliy functions +// utility functions inline CodeSnipList getConversionRule(TypeSystem::Language lang, const AbstractMetaFunction *function) { CodeSnipList list; @@ -2731,7 +2731,7 @@ void CppGenerator::writeRichCompareFunction(QTextStream& s, const AbstractMetaCl s << baseName << "_richcompare(PyObject* self, PyObject* other, int op)" << endl; s << '{' << endl; QList cmpOverloads = filterGroupedOperatorFunctions(metaClass, AbstractMetaClass::ComparisonOp); - s << INDENT << "bool result = false;" << endl; + s << INDENT << "PyObject* result = 0;" << endl; s << INDENT << metaClass->qualifiedCppName() << "& " CPP_SELF_VAR " = *" << cpythonWrapperCPtr(metaClass) << ';' << endl; s << endl; @@ -2784,24 +2784,10 @@ void CppGenerator::writeRichCompareFunction(QTextStream& s, const AbstractMetaCl s << " cppOther = "; writeToCppConversion(s, type, metaClass, "other", ExcludeReference | ExcludeConst); s << ';' << endl; - s << INDENT << "result = (" CPP_SELF_VAR " " << op << " cppOther);" << endl; - } - s << INDENT << '}'; - } - // Compares with implicit conversions - if (comparesWithSameType && !metaClass->implicitConversions().isEmpty()) { - AbstractMetaType temporaryType; - temporaryType.setTypeEntry(metaClass->typeEntry()); - temporaryType.setConstant(false); - temporaryType.setReference(false); - temporaryType.setTypeUsagePattern(AbstractMetaType::ValuePattern); - s << " else if (" << cpythonIsConvertibleFunction(metaClass->typeEntry()); - s << "(other)) {" << endl; - { - Indentation indent(INDENT); - writeArgumentConversion(s, &temporaryType, "cppOther", "other", metaClass); - s << INDENT << "result = (" CPP_SELF_VAR " " << op << " cppOther);" << endl; + s << INDENT << "result = "; + writeToPythonConversion(s, func->type(), metaClass, CPP_SELF_VAR " " + op + " cppOther"); + s << ';' << endl; } s << INDENT << '}'; } @@ -2814,19 +2800,19 @@ void CppGenerator::writeRichCompareFunction(QTextStream& s, const AbstractMetaCl s << INDENT << "default:" << endl; { Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"operator not implemented.\");" << endl; - s << INDENT << "return " << m_currentErrorCode << ';' << endl; + s << INDENT << "goto " << baseName << "_RichComparison_TypeError;" << endl; } } s << INDENT << '}' << endl << endl; - s << INDENT << "if (result)" << endl; + s << INDENT << "if (result && !PyErr_Occurred())" << endl; { Indentation indent(INDENT); - s << INDENT << "Py_RETURN_TRUE;" << endl; + s << INDENT << "return result;" << endl; } s << INDENT << baseName << "_RichComparison_TypeError:" << endl; - s << INDENT << "Py_RETURN_FALSE;" << endl << endl; + s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"operator not implemented.\");" << endl; + s << INDENT << "return " << m_currentErrorCode << ';' << endl << endl; s << '}' << endl << endl; } diff --git a/libshiboken/conversions.h b/libshiboken/conversions.h index 8b312dfe..11423ef6 100644 --- a/libshiboken/conversions.h +++ b/libshiboken/conversions.h @@ -203,7 +203,7 @@ struct ValueTypeConverter template struct ObjectTypeConverter { - static inline bool checkType(PyObject* pyObj) { return PyObject_TypeCheck(pyObj, SbkType()); } + static inline bool checkType(PyObject* pyObj) { return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType()); } /// Py_None objects are the only objects convertible to an object type (in the form of a NULL pointer). static inline bool isConvertible(PyObject* pyObj) { return pyObj == Py_None || PyObject_TypeCheck(pyObj, SbkType()); } /// Convenience overload that calls "toPython(const T*)" method. @@ -452,7 +452,8 @@ struct EnumConverter template struct Converter_CString { - static inline bool checkType(PyObject* pyObj) { return PyString_Check(pyObj); } + // Note: 0 is also a const char* in C++, so None is accepted in checkType + static inline bool checkType(PyObject* pyObj) { return pyObj == Py_None || PyString_Check(pyObj); } static inline bool isConvertible(PyObject* pyObj) { return pyObj == Py_None || PyString_Check(pyObj); } static inline PyObject* toPython(void* cppobj) { return toPython(reinterpret_cast(cppobj)); } static inline PyObject* toPython(CString cppobj) diff --git a/tests/libsample/CMakeLists.txt b/tests/libsample/CMakeLists.txt index 158c0e5e..3452c576 100644 --- a/tests/libsample/CMakeLists.txt +++ b/tests/libsample/CMakeLists.txt @@ -34,6 +34,7 @@ sometime.cpp str.cpp strlist.cpp virtualmethods.cpp +expression.cpp ) include_directories(${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/tests/libsample/expression.cpp b/tests/libsample/expression.cpp new file mode 100644 index 00000000..d93d47f0 --- /dev/null +++ b/tests/libsample/expression.cpp @@ -0,0 +1,127 @@ +/* + * This file is part of the Shiboken Python Binding Generator project. + * + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include "expression.h" +#include + +Expression::Expression() : m_value(0), m_operation(None), m_operand1(0), m_operand2(0) +{ +} + +Expression::Expression(int number) : m_value(number), m_operation(None), m_operand1(0), m_operand2(0) +{ +} + +Expression::Expression(const Expression& other) +{ + m_operand1 = other.m_operand1 ? new Expression(*other.m_operand1) : 0; + m_operand2 = other.m_operand2 ? new Expression(*other.m_operand2) : 0; + m_value = other.m_value; + m_operation = other.m_operation; +} + +Expression& Expression::operator=(const Expression& other) +{ + delete m_operand1; + delete m_operand2; + m_operand1 = other.m_operand1 ? new Expression(*other.m_operand1) : 0; + m_operand2 = other.m_operand2 ? new Expression(*other.m_operand2) : 0; + m_operation = other.m_operation; + m_value = other.m_value; + return *this; +} + +Expression::~Expression() +{ + delete m_operand1; + delete m_operand2; +} + +Expression Expression::operator+(const Expression& other) +{ + Expression expr; + expr.m_operation = Add; + expr.m_operand1 = new Expression(*this); + expr.m_operand2 = new Expression(other); + return expr; +} + +Expression Expression::operator-(const Expression& other) +{ + Expression expr; + expr.m_operation = Add; + expr.m_operand1 = new Expression(*this); + expr.m_operand2 = new Expression(other); + return expr; +} + +Expression Expression::operator<(const Expression& other) +{ + Expression expr; + expr.m_operation = LessThan; + expr.m_operand1 = new Expression(*this); + expr.m_operand2 = new Expression(other); + return expr; +} + +Expression Expression::operator>(const Expression& other) +{ + Expression expr; + expr.m_operation = GreaterThan; + expr.m_operand1 = new Expression(*this); + expr.m_operand2 = new Expression(other); + return expr; +} + +std::string Expression::toString() const +{ + if (m_operation == None) { + std::ostringstream s; + s << m_value; + return s.str(); + } + + std::string result; + result += '('; + result += m_operand1->toString(); + char op; + switch (m_operation) { + case Add: + op = '+'; + break; + case Sub: + op = '-'; + break; + case LessThan: + op = '<'; + break; + case GreaterThan: + op = '<'; + break; + } + result += op; + result += m_operand2->toString(); + result += ')'; + return result; +} + diff --git a/tests/libsample/expression.h b/tests/libsample/expression.h new file mode 100644 index 00000000..608d5b5e --- /dev/null +++ b/tests/libsample/expression.h @@ -0,0 +1,58 @@ +/* + * This file is part of the Shiboken Python Binding Generator project. + * + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifndef EXPRESSION_H +#define EXPRESSION_H + +#include "libsamplemacros.h" +#include + +class LIBSAMPLE_API Expression +{ +public: + enum Operation { + None, Add, Sub, LessThan, GreaterThan + }; + + Expression(int number); + Expression(const Expression& other); + Expression& operator=(const Expression& other); + + ~Expression(); + + Expression operator>(const Expression& other); + Expression operator<(const Expression& other); + Expression operator+(const Expression& other); + Expression operator-(const Expression& other); + + std::string toString() const; +private: + int m_value; + Operation m_operation; + Expression* m_operand1; + Expression* m_operand2; + + Expression(); +}; + +#endif // EXPRESSION_H diff --git a/tests/samplebinding/CMakeLists.txt b/tests/samplebinding/CMakeLists.txt index 5e3498cb..d3e27591 100644 --- a/tests/samplebinding/CMakeLists.txt +++ b/tests/samplebinding/CMakeLists.txt @@ -22,6 +22,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/derived_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/derived_someinnerclass_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/echo_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/event_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/expression_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/handleholder_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/implicitconv_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/implicitbase_wrapper.cpp diff --git a/tests/samplebinding/global.h b/tests/samplebinding/global.h index f85ee69b..d027b0f5 100644 --- a/tests/samplebinding/global.h +++ b/tests/samplebinding/global.h @@ -44,3 +44,4 @@ #include "virtualmethods.h" #include "voidholder.h" #include "valueandvirtual.h" +#include "expression.h" diff --git a/tests/samplebinding/reference_test.py b/tests/samplebinding/reference_test.py index e754449d..abff658c 100644 --- a/tests/samplebinding/reference_test.py +++ b/tests/samplebinding/reference_test.py @@ -64,7 +64,7 @@ def testMethodThatReceivesReference(self): def testCantSegFaultWhenReceiveNone(self): '''do not segfault when receiving None as argument.''' s = Str() - self.assert_(not None == s) + self.assertTrue(None == s) def testMethodThatReceivesConstReference(self): '''Test a method that receives a const reference to an object as argument.''' diff --git a/tests/samplebinding/richcompare_test.py b/tests/samplebinding/richcompare_test.py new file mode 100644 index 00000000..dfd20a37 --- /dev/null +++ b/tests/samplebinding/richcompare_test.py @@ -0,0 +1,41 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# This file is part of the Shiboken Python Bindings Generator project. +# +# Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +# +# Contact: PySide team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# version 2.1 as published by the Free Software Foundation. Please +# review the following information to ensure the GNU Lesser General +# Public License version 2.1 requirements will be met: +# http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +# # +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +import unittest + +from sample import * + +class TestRichCompare(unittest.TestCase): + + def testIt(self): + a = Expression(2) + b = Expression(3) + c = a + b + d = a + c < b + a + self.assertEqual(d.toString(), "((2+(2+3))<(3+2))") + +if __name__ == '__main__': + unittest.main() diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index f0a78e1e..ba58c5f2 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -1255,6 +1255,8 @@ + + From b915f12df2349760309c2f7227bcdbad3c73a7da Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 9 Dec 2010 19:37:41 -0200 Subject: [PATCH 170/564] Finally fix bug#500 - "If an instance of QPrintDialog is created a deadlock happens on shutdown." Reviewer: Luciano Wolf Marcelo Lira --- libshiboken/basewrapper.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index b3fc3801..72615dbb 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -30,6 +30,7 @@ #include #include #include +#include "threadstatesaver.h" extern "C" { @@ -166,10 +167,11 @@ void SbkDeallocWrapper(PyObject* pyObj) Shiboken::DtorCallerVisitor visitor(sbkObj); Shiboken::walkThroughClassHierarchy(pyObj->ob_type, &visitor); } else { + Shiboken::ThreadStateSaver threadSaver; + threadSaver.save(); sbkType->d->cpp_dtor(sbkObj->d->cptr[0]); } } - Shiboken::Object::deallocData(sbkObj, !sbkObj->d->containsCppWrapper); } @@ -317,6 +319,8 @@ bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr) void DtorCallerVisitor::visit(SbkObjectType* node) { + Shiboken::ThreadStateSaver threadSaver; + threadSaver.save(); node->d->cpp_dtor(m_pyObj->d->cptr[m_count]); m_count++; } From fb4035a69475759e58e25d5aa0f061d6c212f4af Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Tue, 14 Dec 2010 15:19:37 -0300 Subject: [PATCH 171/564] Fix object destruction process to avoid pass a invalid object during the __del__ function. Fix bug #505 Reviewer: Luciano Wolf Marcelo Lira --- generator/cppgenerator.cpp | 2 +- libshiboken/basewrapper.cpp | 27 ++++++++++++++++----------- libshiboken/basewrapper.h | 1 + libshiboken/bindingmanager.cpp | 3 ++- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 55747d37..5b7b0d03 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -464,7 +464,7 @@ void CppGenerator::writeDestructorNative(QTextStream &s, const AbstractMetaClass Indentation indentation(INDENT); s << wrapperName(metaClass) << "::~" << wrapperName(metaClass) << "()" << endl << '{' << endl; s << INDENT << "SbkObject* wrapper = Shiboken::BindingManager::instance().retrieveWrapper(this);" << endl; - s << INDENT << "Shiboken::Object::destroy(wrapper);" << endl; + s << INDENT << "Shiboken::Object::destroy(wrapper, this);" << endl; s << '}' << endl; } diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 72615dbb..1f2499d0 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -812,6 +812,11 @@ PyObject* newObject(SbkObjectType* instanceType, } void destroy(SbkObject* self) +{ + destroy(self, 0); +} + +void destroy(SbkObject* self, void* cppData) { // Skip if this is called with NULL pointer this can happen in derived classes if (!self) @@ -820,16 +825,9 @@ void destroy(SbkObject* self) // This can be called in c++ side Shiboken::GilState gil; - // We will marks this object as invalid because this function will be called from wrapper destructor - // If The object has ownership and this was destroyed then is necessary invalidate to avoid future used by Python - self->d->validCppObject = false; - // Remove all references attached to this object clearReferences(self); - // Remove from BindinManager - Shiboken::BindingManager::instance().releaseWrapper(self); - // Remove the object from parent control // Verify if this object has parent @@ -847,6 +845,13 @@ void destroy(SbkObject* self) // This can cause the object death Py_DECREF((PyObject*)self); } + + //Python Object is not destroyed yet + if (cppData && Shiboken::BindingManager::instance().hasWrapper(cppData)) { + // Remove from BindinManager + Shiboken::BindingManager::instance().releaseWrapper(self); + } + // After this point the object can be death do not use the self pointer bellow } @@ -875,7 +880,7 @@ void removeParent(SbkObject* child, bool giveOwnershipBack, bool keepReference) child->d->hasOwnership = giveOwnershipBack; // Remove parent ref - Py_DECREF(child); + Py_CLEAR(child); } void setParent(PyObject* parent, PyObject* child) @@ -951,11 +956,11 @@ void deallocData(SbkObject* self, bool cleanup) _destroyParentInfo(self, true); clearReferences(self); - - // Remove from BindinManager - Shiboken::BindingManager::instance().releaseWrapper(self); } + // Remove from BindinManager + Shiboken::BindingManager::instance().releaseWrapper(self); + Py_XDECREF(self->ob_dict); delete[] self->d->cptr; self->d->cptr = 0; diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 46bc641d..99e35474 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -294,6 +294,7 @@ LIBSHIBOKEN_API void makeValid(SbkObject* self); * Destroy any data in Shiboken structure and c++ pointer if the pyboject has the ownership **/ LIBSHIBOKEN_API void destroy(SbkObject* self); +LIBSHIBOKEN_API void destroy(SbkObject* self, void* cppData); /** * Set user data on type of \p wrapper. diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index 2bcf2deb..68bfe485 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -148,7 +148,7 @@ BindingManager::~BindingManager() * the BindingManager is being destroyed the interpreter is alredy * shutting down. */ while (!m_d->wrapperMapper.empty()) { - Object::destroy(m_d->wrapperMapper.begin()->second); + Object::destroy(m_d->wrapperMapper.begin()->second, const_cast(m_d->wrapperMapper.begin()->first)); } assert(m_d->wrapperMapper.size() == 0); delete m_d; @@ -204,6 +204,7 @@ void BindingManager::releaseWrapper(SbkObject* sbkObj) } } } + sbkObj->d->validCppObject = false; } SbkObject* BindingManager::retrieveWrapper(const void* cptr) From 709235038fc2ee25984e01759403f1f8a75338f7 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Wed, 15 Dec 2010 17:55:36 -0300 Subject: [PATCH 172/564] Fixed comments typo. --- libshiboken/basewrapper.cpp | 4 ++-- libshiboken/basewrapper.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 1f2499d0..f40e90be 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -848,7 +848,7 @@ void destroy(SbkObject* self, void* cppData) //Python Object is not destroyed yet if (cppData && Shiboken::BindingManager::instance().hasWrapper(cppData)) { - // Remove from BindinManager + // Remove from BindingManager Shiboken::BindingManager::instance().releaseWrapper(self); } @@ -958,7 +958,7 @@ void deallocData(SbkObject* self, bool cleanup) clearReferences(self); } - // Remove from BindinManager + // Remove from BindingManager Shiboken::BindingManager::instance().releaseWrapper(self); Py_XDECREF(self->ob_dict); diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 99e35474..bab83a08 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -293,7 +293,7 @@ LIBSHIBOKEN_API void makeValid(SbkObject* self); /** * Destroy any data in Shiboken structure and c++ pointer if the pyboject has the ownership **/ -LIBSHIBOKEN_API void destroy(SbkObject* self); +LIBSHIBOKEN_API void destroy(SbkObject* self); //DEPRECATED LIBSHIBOKEN_API void destroy(SbkObject* self, void* cppData); /** From 5d07b706d29cb80aa10b34fad1f883a78266a9c2 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Wed, 15 Dec 2010 17:55:51 -0300 Subject: [PATCH 173/564] Replaced code generated on funtion getattro to function present on libpyside. Fix bug #525. --- generator/cppgenerator.cpp | 84 ++------------------------------------ 1 file changed, 4 insertions(+), 80 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 5b7b0d03..58213781 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -3415,86 +3415,10 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, const AbstractMetaClass } s << INDENT << '}' << endl; } - s << INDENT << "PyObject* attr = PyObject_GenericGetAttr(self, name);" << endl; - if (usePySideExtensions() && (metaClass->qualifiedCppName() == "QObject")) { - s << INDENT << "if (attr && PySide::Property::isPropertyType(attr)) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyObject *value = PySide::Property::getValue(reinterpret_cast(attr), self);" << endl; - s << INDENT << "if (!value)" << endl; - { - Indentation indentation(INDENT); - s << INDENT << "return " << m_currentErrorCode << ';' << endl; - } - s << INDENT << "Py_DECREF(attr);" << endl; - s << INDENT << "Py_INCREF(value);" << endl; - s << INDENT << "attr = value;" << endl; - } - s << INDENT << "}" << endl; - - //mutate native signals to signal instance type - s << INDENT << "if (attr && PyObject_TypeCheck(attr, &PySideSignalType)) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyObject* signal = reinterpret_cast(PySide::Signal::initialize(reinterpret_cast(attr), name, self));" << endl - << INDENT << "PyObject_SetAttr(self, name, reinterpret_cast(signal));" << endl - << INDENT << "return signal;" << endl; - } - s << INDENT << "}" << endl; - - //search on metaobject (avoid internal attributes started with '__')"; - s << INDENT << "if (!attr && !QString(PyString_AS_STRING(name)).startsWith(\"__\")) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "QObject* cppSelf = Shiboken::Converter::toCpp(self);" << endl - << INDENT << "const QMetaObject* metaObject = cppSelf->metaObject();" << endl - << INDENT << "QByteArray cname(PyString_AS_STRING(name));" << endl - << INDENT << "cname += '(';" << endl - << INDENT << "//signal" << endl - << INDENT << "QList signalList;" << endl - << INDENT << "for(int i=0, i_max = metaObject->methodCount(); i < i_max; i++) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "QMetaMethod method = metaObject->method(i);" << endl - << INDENT << "if (QString(method.signature()).startsWith(cname)) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "if (method.methodType() == QMetaMethod::Signal) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "signalList.append(method);" << endl; - } - s << INDENT << "} else {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PySideMetaFunction* func = PySide::MetaFunction::newObject(cppSelf, i);" << endl - << INDENT << "if (func) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyObject_SetAttr(self, name, (PyObject*)func);" << endl - << INDENT << "return (PyObject*)func;" << endl; - } - s << INDENT << "}" << endl; - } - s << INDENT << "}" << endl; - } - s << INDENT << "}" << endl; - - } - s << INDENT << "}" << endl - << INDENT << "if (signalList.size() > 0) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyObject* pySignal = reinterpret_cast(PySide::Signal::newObjectFromMethod(self, signalList));" << endl - << INDENT << "PyObject_SetAttr(self, name, pySignal);" << endl - << INDENT << "return pySignal;" << endl; - } - s << INDENT << "}" << endl; - } - s << INDENT << "}" << endl; - } - - s << INDENT << "return attr;" << endl; + if (usePySideExtensions() && metaClass->isQObject()) + s << INDENT << "return PySide::getMetaDataFromQObject(Shiboken::Converter::toCpp(self), self, name);" << endl; + else + s << INDENT << "return PyObject_GenericGetAttr(self, name);" << endl; s << '}' << endl; } From 4b866fc793113e84c276eb972eb99a457074018c Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Wed, 15 Dec 2010 18:28:27 -0300 Subject: [PATCH 174/564] Fixed typo on generated error message. --- generator/cppgenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 58213781..29a70582 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -758,7 +758,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu s << INDENT << "if (" << PYTHON_RETURN_VAR << "->ob_refcnt < 2) {" << endl; { Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_ReferenceError, \"Returning last python reference on virutal function: " + s << INDENT << "PyErr_SetString(PyExc_ReferenceError, \"Returning last python reference on virtual function: " << func->ownerClass()->name() << "." << func->name() << "\");" << endl; s << INDENT << "PyErr_Print();" << endl; s << INDENT << "assert(false);" << endl; From f728e59aa228d5b796b5641bea683333b10919e4 Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Wed, 15 Dec 2010 18:29:06 -0300 Subject: [PATCH 175/564] Generate code to release ownership on Python values returned to C++ on virtual methods. In other words, the following type system snippet will now be recognized by the generator: --- generator/cppgenerator.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 29a70582..7664fb98 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -743,6 +743,16 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu Indentation indentation(INDENT); s << INDENT << "Shiboken::Object::invalidate(PyTuple_GET_ITEM(pyargs, "; s << (argMod.index - 1) << "));" << endl; + } else if (argMod.ownerships.contains(TypeSystem::NativeCode)) { + if (argMod.index == 0 && argMod.ownerships[TypeSystem::NativeCode] == TypeSystem::CppOwnership) { + s << INDENT << "if (Shiboken::Object::checkType(" PYTHON_RETURN_VAR ")) {" << endl; + { + Indentation indent(INDENT); + s << INDENT << "Shiboken::Object::releaseOwnership(" PYTHON_RETURN_VAR ");" << endl; + s << INDENT << "Py_DECREF((PyObject*) " PYTHON_RETURN_VAR ");" << endl; + } + s << INDENT << '}' << endl; + } } } } From 2d146fad966ae24940c65812cde4c28b645ecf6b Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Thu, 16 Dec 2010 14:08:29 -0300 Subject: [PATCH 176/564] Added tests to check the release of ownership of objects returned from Python. The ObjectModel test class was introduced to check if the transference of ownership of objects returned from Python to C++ through a virtual method is working properly. Also updated the other test that uses the ObjectView class. Reviewed by Lauro Moura Reviewed by Luciano Wolf --- tests/libsample/CMakeLists.txt | 1 + tests/libsample/objectmodel.cpp | 36 +++++++++++ tests/libsample/objectmodel.h | 46 ++++++++++++++ tests/libsample/objectview.cpp | 8 ++- tests/libsample/objectview.h | 11 ++-- tests/samplebinding/CMakeLists.txt | 1 + tests/samplebinding/global.h | 1 + tests/samplebinding/keep_reference_test.py | 10 +-- tests/samplebinding/modelview_test.py | 73 ++++++++++++++++++++++ tests/samplebinding/typesystem_sample.xml | 9 ++- 10 files changed, 185 insertions(+), 11 deletions(-) create mode 100644 tests/libsample/objectmodel.cpp create mode 100644 tests/libsample/objectmodel.h create mode 100644 tests/samplebinding/modelview_test.py diff --git a/tests/libsample/CMakeLists.txt b/tests/libsample/CMakeLists.txt index 3452c576..b6cd1b92 100644 --- a/tests/libsample/CMakeLists.txt +++ b/tests/libsample/CMakeLists.txt @@ -16,6 +16,7 @@ modifications.cpp mapuser.cpp modified_constructor.cpp multiple_derived.cpp +objectmodel.cpp objecttype.cpp objecttypelayout.cpp objectview.cpp diff --git a/tests/libsample/objectmodel.cpp b/tests/libsample/objectmodel.cpp new file mode 100644 index 00000000..93c25645 --- /dev/null +++ b/tests/libsample/objectmodel.cpp @@ -0,0 +1,36 @@ +/* + * This file is part of the Shiboken Python Binding Generator project. + * + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "objectmodel.h" + +void +ObjectModel::setData(ObjectType* data) +{ + m_data = data; +} + +ObjectType* +ObjectModel::data() const +{ + return m_data; +} + diff --git a/tests/libsample/objectmodel.h b/tests/libsample/objectmodel.h new file mode 100644 index 00000000..b226b1f9 --- /dev/null +++ b/tests/libsample/objectmodel.h @@ -0,0 +1,46 @@ +/* + * This file is part of the Shiboken Python Binding Generator project. + * + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OBJECTMODEL_H +#define OBJECTMODEL_H + +#include "objecttype.h" +#include "libsamplemacros.h" + +class LIBSAMPLE_API ObjectModel : public ObjectType +{ +public: + ObjectModel(ObjectType* parent = 0) + : ObjectType(parent), m_data(0) + {} + + void setData(ObjectType* data); + virtual ObjectType* data() const; + +private: + // The model holds only one piece of data. + // (This is just a test after all.) + ObjectType* m_data; +}; + +#endif // OBJECTMODEL_H + diff --git a/tests/libsample/objectview.cpp b/tests/libsample/objectview.cpp index 835e7183..a5dbc0f1 100644 --- a/tests/libsample/objectview.cpp +++ b/tests/libsample/objectview.cpp @@ -21,7 +21,7 @@ */ #include "objectview.h" -#include "objecttype.h" +#include "objectmodel.h" #include "str.h" Str @@ -40,3 +40,9 @@ ObjectView::modifyModelData(Str& data) } +ObjectType* +ObjectView::getRawModelData() +{ + return m_model->data(); +} + diff --git a/tests/libsample/objectview.h b/tests/libsample/objectview.h index fd3d640b..3402b6d8 100644 --- a/tests/libsample/objectview.h +++ b/tests/libsample/objectview.h @@ -27,22 +27,25 @@ #include "libsamplemacros.h" class Str; +class ObjectModel; class LIBSAMPLE_API ObjectView : public ObjectType { public: - ObjectView(ObjectType* model = 0, ObjectType* parent = 0) + ObjectView(ObjectModel* model = 0, ObjectType* parent = 0) : ObjectType(parent), m_model(model) {} - inline void setModel(ObjectType* model) { m_model = model; } - inline ObjectType* model() const { return m_model; } + inline void setModel(ObjectModel* model) { m_model = model; } + inline ObjectModel* model() const { return m_model; } Str displayModelData(); void modifyModelData(Str& data); + ObjectType* getRawModelData(); + private: - ObjectType* m_model; + ObjectModel* m_model; }; #endif // OBJECTVIEW_H diff --git a/tests/samplebinding/CMakeLists.txt b/tests/samplebinding/CMakeLists.txt index d3e27591..052e246a 100644 --- a/tests/samplebinding/CMakeLists.txt +++ b/tests/samplebinding/CMakeLists.txt @@ -42,6 +42,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/modifications_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/modifiedconstructor_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/noimplicitconversion_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/nondefaultctor_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/objectmodel_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/objecttype_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/objecttypelayout_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/objectview_wrapper.cpp diff --git a/tests/samplebinding/global.h b/tests/samplebinding/global.h index d027b0f5..90cae083 100644 --- a/tests/samplebinding/global.h +++ b/tests/samplebinding/global.h @@ -20,6 +20,7 @@ #include "multiple_derived.h" #include "noimplicitconversion.h" #include "nondefaultctor.h" +#include "objectmodel.h" #include "objecttype.h" #include "objecttypelayout.h" #include "objecttypereference.h" diff --git a/tests/samplebinding/keep_reference_test.py b/tests/samplebinding/keep_reference_test.py index 13730553..fd99a23c 100644 --- a/tests/samplebinding/keep_reference_test.py +++ b/tests/samplebinding/keep_reference_test.py @@ -29,14 +29,14 @@ import unittest from sys import getrefcount -from sample import ObjectType, ObjectView +from sample import ObjectModel, ObjectView class TestKeepReference(unittest.TestCase): '''Test case for objects that keep references to other object without owning them (e.g. model/view relationships).''' def testReferenceCounting(self): '''Tests reference count of model-like object referred by view-like objects.''' - model1 = ObjectType() + model1 = ObjectModel() refcount1 = getrefcount(model1) view1 = ObjectView() view1.setModel(model1) @@ -46,13 +46,13 @@ def testReferenceCounting(self): view2.setModel(model1) self.assertEqual(getrefcount(view2.model()), refcount1 + 2) - model2 = ObjectType() + model2 = ObjectModel() view2.setModel(model2) self.assertEqual(getrefcount(view1.model()), refcount1 + 1) def testReferenceCountingWhenDeletingReferrer(self): '''Tests reference count of model-like object referred by deceased view-like object.''' - model = ObjectType() + model = ObjectModel() refcount1 = getrefcount(model) view = ObjectView() view.setModel(model) @@ -64,7 +64,7 @@ def testReferenceCountingWhenDeletingReferrer(self): def testReferreedObjectSurvivalAfterContextEnd(self): '''Model-like object assigned to a view-like object must survive after get out of context.''' def createModelAndSetToView(view): - model = ObjectType() + model = ObjectModel() model.setObjectName('created model') view.setModel(model) view = ObjectView() diff --git a/tests/samplebinding/modelview_test.py b/tests/samplebinding/modelview_test.py new file mode 100644 index 00000000..9f86166d --- /dev/null +++ b/tests/samplebinding/modelview_test.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# This file is part of the Shiboken Python Bindings Generator project. +# +# Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +# +# Contact: PySide team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# version 2.1 as published by the Free Software Foundation. Please +# review the following information to ensure the GNU Lesser General +# Public License version 2.1 requirements will be met: +# http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +# # +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +'''Test case for objects that keep references to other object without owning them (e.g. model/view relationships).''' + +import unittest +from sample import ObjectModel, ObjectType, ObjectView + + +object_name = 'test object' + +class MyObject(ObjectType): + pass + +class ListModelKeepsReference(ObjectModel): + def __init__(self, parent=None): + ObjectModel.__init__(self, parent) + self.obj = MyObject() + self.obj.setObjectName(object_name) + + def data(self): + return self.obj + +class ListModelDoesntKeepsReference(ObjectModel): + def data(self): + obj = MyObject() + obj.setObjectName(object_name) + return obj + + +class ModelViewTest(unittest.TestCase): + + def testListModelDoesntKeepsReference(self): + model = ListModelDoesntKeepsReference() + view = ObjectView(model) + obj = view.getRawModelData() + self.assertEqual(type(obj), ObjectType) + self.assertEqual(obj.objectName(), object_name) + + def testListModelKeepsReference(self): + model = ListModelKeepsReference() + view = ObjectView(model) + obj = view.getRawModelData() + self.assertEqual(type(obj), MyObject) + self.assertEqual(obj.objectName(), object_name) + + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index ba58c5f2..ae6f61b9 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -236,13 +236,20 @@ - + + + + + + + + From 45d4e4b0eabc87cd50613a469ce400434b833d6d Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Thu, 16 Dec 2010 15:58:23 -0300 Subject: [PATCH 177/564] Fix register type function to register the type with two names. Fix signal register, to use arguments type name based on generated namespace. Fix bug #498. --- generator/cppgenerator.cpp | 89 +++++++++++++++++++++++++++++--------- generator/cppgenerator.h | 4 ++ 2 files changed, 72 insertions(+), 21 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 7664fb98..2b5a4584 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -84,6 +84,14 @@ inline AbstractMetaType* getTypeWithoutContainer(AbstractMetaType* arg) return arg; } +static QString reduceTypeName(const AbstractMetaClass* metaClass) +{ + QString qualifiedCppName = metaClass->typeEntry()->qualifiedCppName(); + QString lookupName = metaClass->typeEntry()->lookupName(); + if (lookupName != qualifiedCppName) + return lookupName; + return QString(); +} CppGenerator::CppGenerator() : m_currentErrorCode(0) { @@ -123,6 +131,47 @@ QList CppGenerator::filterGroupedOperatorFunctions(con return results.values(); } +void CppGenerator::writeRegisterType(QTextStream& s, const AbstractMetaClass* metaClass) +{ + QString typeName = metaClass->qualifiedCppName(); + QString reducedName = reduceTypeName(metaClass); + + bool isObjectType = metaClass->typeEntry()->isObject(); + if (!isObjectType) { + s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver<" << typeName << " >" << "(\"" << typeName << "\");\n"; + if (!reducedName.isEmpty()) + s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver<" << typeName << " >" << "(\"" << reducedName << "\");\n"; + } + + s << INDENT << "Shiboken::TypeResolver::createObjectTypeResolver<" << typeName << " >" << "(\"" << typeName << "*\");\n"; + if (!reducedName.isEmpty()) + s << INDENT << "Shiboken::TypeResolver::createObjectTypeResolver<" << typeName << " >" << "(\"" << reducedName << "*\");\n"; + QString functionSufix = (isObjectType ? "Object" : "Value"); + s << INDENT << "Shiboken::TypeResolver::create" << functionSufix; + s << "TypeResolver<" << typeName << " >" << "(typeid(" << typeName << ").name());\n"; + if (shouldGenerateCppWrapper(metaClass)) { + s << INDENT << "Shiboken::TypeResolver::create" << functionSufix; + s << "TypeResolver<" << typeName << " >" << "(typeid(" << wrapperName(metaClass) << ").name());\n"; + } +} + +void CppGenerator::writeRegisterType(QTextStream& s, const AbstractMetaEnum* metaEnum) +{ + QString fullName; + QString shortName; + if (metaEnum->enclosingClass()) { + QString suffix = "::" + metaEnum->name(); + fullName = metaEnum->enclosingClass()->qualifiedCppName() + suffix; + shortName = reduceTypeName(metaEnum->enclosingClass()) + suffix; + } else { + fullName = metaEnum->name(); + } + s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver(\"" << fullName << "\");\n"; + if (!shortName.isEmpty()) + s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver(\"" << shortName << "\");\n"; + +} + void CppGenerator::writeToPythonFunction(QTextStream& s, const AbstractMetaClass* metaClass) { s << "static PyObject* " << cpythonBaseName(metaClass) << "_ToPythonFunc(PyObject* self)" << endl; @@ -2960,16 +3009,26 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu if (!cppEnum->isAnonymous()) { // TypeResolver stuff - s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver(\""; - if (cppEnum->enclosingClass()) - s << cppEnum->enclosingClass()->qualifiedCppName() << "::"; - s << cppEnum->name() << "\");\n"; + writeRegisterType(s, cppEnum); } s << INDENT << "// end of enum " << cppEnum->name() << endl << endl; } +static QString skipNamespace(const QString& typeName) +{ + QString namespaceName = typeName.split("::").first(); + if (namespaceName.isEmpty()) + return typeName; + + NamespaceTypeEntry* entry = TypeDatabase::instance()->findNamespaceType(namespaceName); + if (entry && !entry->generateCode()) + return QString(typeName).replace(namespaceName + "::", ""); + + return typeName; +} + void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaClass* metaClass) { QHash signatures; @@ -2982,6 +3041,7 @@ void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaC for (int i = 0; i < cppSignal->arguments().count(); ++i) { if (i > 0) signature += ", "; + AbstractMetaArgument *a = cppSignal->arguments().at(i); AbstractMetaType* type = a->type(); QString cppSignature = QMetaObject::normalizedType(qPrintable(type->cppSignature())); @@ -2998,9 +3058,9 @@ void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaC knowTypes << originalSignature; s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver<" << cppSignature << " >" - << "(\"" << originalSignature << "\"); // " << type->cppSignature() << "\n"; + << "(\"" << skipNamespace(originalSignature) << "\"); // " << type->cppSignature() << "\n"; } - signature += type->originalTypeDescription(); + signature += skipNamespace(type->originalTypeDescription()); } } else { signature = "void"; @@ -3312,21 +3372,8 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), CodeSnip::End, TypeSystem::TargetLangCode, 0, 0, metaClass); } - if (!metaClass->isNamespace()) { - bool isObjectType = metaClass->typeEntry()->isObject(); - QString typeName = metaClass->qualifiedCppName(); - if (!isObjectType) - s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver<" << typeName << " >" << "(\"" << typeName << "\");\n"; - - s << INDENT << "Shiboken::TypeResolver::createObjectTypeResolver<" << typeName << " >" << "(\"" << typeName << "*\");\n"; - QString functionSufix = (isObjectType ? "Object" : "Value"); - s << INDENT << "Shiboken::TypeResolver::create" << functionSufix; - s << "TypeResolver<" << typeName << " >" << "(typeid(" << typeName << ").name());\n"; - if (shouldGenerateCppWrapper(metaClass)) { - s << INDENT << "Shiboken::TypeResolver::create" << functionSufix; - s << "TypeResolver<" << typeName << " >" << "(typeid(" << wrapperName(metaClass) << ").name());\n"; - } - } + if (!metaClass->isNamespace()) + writeRegisterType(s, metaClass); if (usePySideExtensions() && !metaClass->isNamespace()) { // Qt metatypes are registered only on their first use, so we do this now. diff --git a/generator/cppgenerator.h b/generator/cppgenerator.h index 6e064dd4..f2bc30e0 100644 --- a/generator/cppgenerator.h +++ b/generator/cppgenerator.h @@ -192,10 +192,14 @@ class CppGenerator : public ShibokenGenerator void writeStdListWrapperMethods(QTextStream& s, const AbstractMetaClass* metaClass); QString writeReprFunction(QTextStream& s, const AbstractMetaClass* metaClass); + void writeRegisterType(QTextStream& s, const AbstractMetaClass* metaClass); + void writeRegisterType(QTextStream& s, const AbstractMetaEnum* metaEnum); + // Maps special function names to function parameters and return types // used by CPython API in the sequence protocol. QHash > m_sequenceProtocol; int m_currentErrorCode; + }; #endif // CPPGENERATOR_H From 81423ee9987008864cf1d66d009afc815c2419e5 Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Fri, 17 Dec 2010 11:00:24 -0300 Subject: [PATCH 178/564] Fixed code generation for virtual method ownership release of returned value. The value returned from Python to C++ shouldn't have its reference counting decremented after Python transferring ownership to C++. --- generator/cppgenerator.cpp | 4 +--- tests/samplebinding/modelview_test.py | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 2b5a4584..8a922729 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -794,13 +794,11 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu s << (argMod.index - 1) << "));" << endl; } else if (argMod.ownerships.contains(TypeSystem::NativeCode)) { if (argMod.index == 0 && argMod.ownerships[TypeSystem::NativeCode] == TypeSystem::CppOwnership) { - s << INDENT << "if (Shiboken::Object::checkType(" PYTHON_RETURN_VAR ")) {" << endl; + s << INDENT << "if (Shiboken::Object::checkType(" PYTHON_RETURN_VAR "))" << endl; { Indentation indent(INDENT); s << INDENT << "Shiboken::Object::releaseOwnership(" PYTHON_RETURN_VAR ");" << endl; - s << INDENT << "Py_DECREF((PyObject*) " PYTHON_RETURN_VAR ");" << endl; } - s << INDENT << '}' << endl; } } } diff --git a/tests/samplebinding/modelview_test.py b/tests/samplebinding/modelview_test.py index 9f86166d..7b9bfe7b 100644 --- a/tests/samplebinding/modelview_test.py +++ b/tests/samplebinding/modelview_test.py @@ -57,7 +57,7 @@ def testListModelDoesntKeepsReference(self): model = ListModelDoesntKeepsReference() view = ObjectView(model) obj = view.getRawModelData() - self.assertEqual(type(obj), ObjectType) + self.assertEqual(type(obj), MyObject) self.assertEqual(obj.objectName(), object_name) def testListModelKeepsReference(self): From 9459b9da9c85ec0f54d945ffa5b19174c285d9ac Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Fri, 17 Dec 2010 11:05:53 -0300 Subject: [PATCH 179/564] Removed unnecessary code to check the refcount of Python objects returned on virtual methods. Reviewed by Hugo Parente Reviewed by Luciano Wolf --- generator/cppgenerator.cpp | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 8a922729..2f116520 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -810,20 +810,8 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu writeCodeSnips(s, snips, CodeSnip::End, TypeSystem::NativeCode, func, lastArg); } - if (type) { - if (!invalidateReturn && (func->type()->isObject() || func->type()->isValuePointer()) ) { - s << INDENT << "if (" << PYTHON_RETURN_VAR << "->ob_refcnt < 2) {" << endl; - { - Indentation indent(INDENT); - s << INDENT << "PyErr_SetString(PyExc_ReferenceError, \"Returning last python reference on virtual function: " - << func->ownerClass()->name() << "." << func->name() << "\");" << endl; - s << INDENT << "PyErr_Print();" << endl; - s << INDENT << "assert(false);" << endl; - } - s << INDENT << "}" << endl; - } + if (type) s << INDENT << "return " CPP_RETURN_VAR ";" << endl; - } s << '}' << endl << endl; } From 94f1ca48808d215c4aa0a7ed2e3459c13a9ade7f Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Mon, 20 Dec 2010 13:49:15 -0200 Subject: [PATCH 180/564] Disable copy of ThreadStateSaver objects. --- libshiboken/threadstatesaver.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libshiboken/threadstatesaver.h b/libshiboken/threadstatesaver.h index fe2a80e6..5b293511 100644 --- a/libshiboken/threadstatesaver.h +++ b/libshiboken/threadstatesaver.h @@ -38,6 +38,9 @@ class LIBSHIBOKEN_API ThreadStateSaver void restore(); private: PyThreadState* m_threadState; + + ThreadStateSaver(const ThreadStateSaver&); + ThreadStateSaver& operator=(const ThreadStateSaver&); }; } // namespace Shiboken From 6d4f397eb58c205adc307c23b1c343cbec388489 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Mon, 20 Dec 2010 13:50:01 -0200 Subject: [PATCH 181/564] Fix bug#484 - "Error compiling QtContacts 1.1 (problems with const QList)" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Renato Araújo Marcelo Lira --- generator/shibokengenerator.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/generator/shibokengenerator.cpp b/generator/shibokengenerator.cpp index 8be8964e..697c89e5 100644 --- a/generator/shibokengenerator.cpp +++ b/generator/shibokengenerator.cpp @@ -1660,12 +1660,14 @@ Generator::Options ShibokenGenerator::getConverterOptions(const AbstractMetaType Options flags; const TypeEntry* type = metaType->typeEntry(); bool isCStr = isCString(metaType); - if (metaType->indirections() && !isCStr) + if (metaType->indirections() && !isCStr) { flags = ExcludeConst; - else if (type->isPrimitive() && !isCStr) + } else if (metaType->isContainer() + || (type->isPrimitive() && !isCStr) + // const refs become just the value, but pure refs must remain pure. + || (type->isValue() && metaType->isConstant() && metaType->isReference())) { flags = ExcludeConst | ExcludeReference; - else if (type->isValue() && metaType->isConstant() && metaType->isReference()) - flags = ExcludeConst | ExcludeReference; // const refs become just the value, but pure refs must remain pure. + } return flags; } From f5422ac1aa196c8c061e2e294fe96bbf886013b7 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Wed, 22 Dec 2010 11:14:54 -0300 Subject: [PATCH 182/564] Fixed use of python conversion for type with typedefs. Reviewer: Marcelo Lira Hugo Parente --- generator/cppgenerator.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 2f116520..f7ee298b 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -632,9 +632,11 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu || arg->type()->isFlags() || arg->type()->isEnum() || arg->type()->isContainer() - || arg->type()->isReference() - || (arg->type()->isPrimitive() - && !m_formatUnits.contains(arg->type()->typeEntry()->name())); + || arg->type()->isReference(); + + //leave the conversion to python + if (arg->type()->isPrimitive() && (m_formatUnits.contains(arg->type()->typeEntry()->name()) || m_formatUnits.contains(arg->type()->typeEntry()->qualifiedCppName()))) + convert = false; bool hasConversionRule = !func->conversionRule(TypeSystem::TargetLangCode, arg->argumentIndex() + 1).isEmpty(); From 8ac60d130d1735156345839dfc12a061adfdb1f0 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Wed, 22 Dec 2010 12:39:41 -0300 Subject: [PATCH 183/564] Use converter during generation only for primitives types which is impossible to convert using by Py_BuildValue. Reviewer: Marcelo Lira Hugo Parente --- generator/cppgenerator.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index f7ee298b..5fa06882 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -624,19 +624,25 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu QString argConv; QTextStream ac(&argConv); - bool convert = arg->type()->isObject() + const PrimitiveTypeEntry* argType = (const PrimitiveTypeEntry*) arg->type()->typeEntry(); + bool convert = argType->isObject() || arg->type()->isQObject() - || arg->type()->isValue() + || argType->isValue() || arg->type()->isValuePointer() || arg->type()->isNativePointer() - || arg->type()->isFlags() - || arg->type()->isEnum() - || arg->type()->isContainer() + || argType->isFlags() + || argType->isEnum() + || argType->isContainer() || arg->type()->isReference(); - //leave the conversion to python - if (arg->type()->isPrimitive() && (m_formatUnits.contains(arg->type()->typeEntry()->name()) || m_formatUnits.contains(arg->type()->typeEntry()->qualifiedCppName()))) - convert = false; + if (!convert && argType->isPrimitive()) { + if (argType->basicAliasedTypeEntry()) + argType = argType->basicAliasedTypeEntry(); + if (m_formatUnits.contains(argType->name())) + convert = false; + else + convert = true; + } bool hasConversionRule = !func->conversionRule(TypeSystem::TargetLangCode, arg->argumentIndex() + 1).isEmpty(); From 234091a597d14a1c127b406883324f65a534cde0 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Mon, 20 Dec 2010 19:24:34 -0200 Subject: [PATCH 184/564] Print debug messages to stderr isntead of stdout. --- libshiboken/bindingmanager.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index 68bfe485..3aa4c88e 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -91,16 +91,16 @@ class Graph #ifndef NDEBUG static void showWrapperMap(const WrapperMap& wrapperMap) { - printf("-------------------------------\n"); - printf("WrapperMap: %p (size: %d)\n", &wrapperMap, (int) wrapperMap.size()); + fprintf(stderr, "-------------------------------\n"); + fprintf(stderr, "WrapperMap: %p (size: %d)\n", &wrapperMap, (int) wrapperMap.size()); WrapperMap::const_iterator iter; for (iter = wrapperMap.begin(); iter != wrapperMap.end(); ++iter) { - printf("key: %p, value: %p (%s, refcnt: %d)\n", iter->first, + fprintf(stderr, "key: %p, value: %p (%s, refcnt: %d)\n", iter->first, iter->second, iter->second->ob_type->tp_name, (int) iter->second->ob_refcnt); } - printf("-------------------------------\n"); + fprintf(stderr, "-------------------------------\n"); } #endif From 4399a96c668ed38473184f1c389334acacee20e5 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 22 Dec 2010 18:46:26 -0200 Subject: [PATCH 185/564] Removed WITH_THREAD ifdefs, it causes a lot of warnings on Windows and was always set by our buildsystem. --- libshiboken/CMakeLists.txt | 1 - libshiboken/basewrapper.cpp | 2 -- 2 files changed, 3 deletions(-) diff --git a/libshiboken/CMakeLists.txt b/libshiboken/CMakeLists.txt index a329eec0..36156065 100644 --- a/libshiboken/CMakeLists.txt +++ b/libshiboken/CMakeLists.txt @@ -15,7 +15,6 @@ else() set(SPARSEHASH_INCLUDE_PATH ${CMAKE_SOURCE_DIR}/ext/sparsehash) endif() -add_definitions(-DWITH_THREAD) set(libshiboken_MAJOR_VERSION ${shiboken_MAJOR_VERSION}) set(libshiboken_MINOR_VERSION ${shiboken_MINOR_VERSION}) set(libshiboken_MICRO_VERSION ${shiboken_MICRO_VERSION}) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index f40e90be..ba26c965 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -332,9 +332,7 @@ void init() return; initTypeResolver(); -#ifdef WITH_THREAD PyEval_InitThreads(); -#endif if (PyType_Ready(&SbkEnumType_Type) < 0) Py_FatalError("[libshiboken] Failed to initialise Shiboken.SbkEnumType metatype."); From ba3791086fc50efb7beeb28302cd7aad67f06af8 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 22 Dec 2010 18:50:54 -0200 Subject: [PATCH 186/564] Minor changed in CMakeLists.txt --- CMakeLists.txt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 80eb5d38..cfacdb84 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,10 +92,6 @@ if(APPLE) set(SBK_PYTHON_LIBRARIES "-undefined dynamic_lookup") endif() -if (BUILD_TESTS) - enable_testing() -endif() - add_subdirectory(libshiboken) add_subdirectory(doc) @@ -104,10 +100,11 @@ if (QT4_FOUND AND ApiExtractor_FOUND AND GeneratorRunner_FOUND AND PYTHONLIBS_FO add_subdirectory(generator) if (BUILD_TESTS) + enable_testing() add_subdirectory(tests) endif() else() - message("!! Some dependencies were not found, shiboken generator compilation disabled!") + message(WARNING "Some dependencies were not found, shiboken generator compilation disabled!") endif() if(CMAKE_VERSION VERSION_LESS 2.8) @@ -115,8 +112,10 @@ if(CMAKE_VERSION VERSION_LESS 2.8) else() set(SBK_PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_DIRS}) endif() + add_subdirectory(data) +# dist target set(ARCHIVE_NAME ${CMAKE_PROJECT_NAME}-${shiboken_VERSION}) add_custom_target(dist COMMAND mkdir -p "${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}" && From 473da995f2ba6f8277b0df7cf4b96a5b36b7edc6 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 22 Dec 2010 19:17:02 -0200 Subject: [PATCH 187/564] Fix Py_DEBUG detection on Windows. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Windows sysconfig.get('Py_DEBUG') can return None instead of 0. Reviewer: Marcelo Lira Renato Araújo --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cfacdb84..d0891ce9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,7 +66,7 @@ add_custom_target(uninstall "${CMAKE_COMMAND}" # Detect if the python libs were compiled in debug mode execute_process( COMMAND ${PYTHON_EXECUTABLE} -c "from distutils import sysconfig; \\ - print sysconfig.get_config_var('Py_DEBUG')" + print bool(sysconfig.get_config_var('Py_DEBUG'))" OUTPUT_VARIABLE PY_DEBUG OUTPUT_STRIP_TRAILING_WHITESPACE) From ec2ca67a1b93b5890dacaa3683c0a6079906bd5b Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Wed, 22 Dec 2010 19:46:49 -0300 Subject: [PATCH 188/564] Fixed signal register function. Use translated type name as type, and exclude const from containers. Reviewer: Lauro Moura Hugo Parente Lima --- generator/cppgenerator.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 5fa06882..de4c9234 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -3050,8 +3050,11 @@ void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaC if ((cppSignature != originalSignature) && !knowTypes.contains(originalSignature)) { knowTypes << originalSignature; + Options opt = NoOption; + if (type->isContainer()) + opt = ExcludeConst; s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver<" - << cppSignature << " >" + << translateType(type, metaClass, opt) << " >" << "(\"" << skipNamespace(originalSignature) << "\"); // " << type->cppSignature() << "\n"; } signature += skipNamespace(type->originalTypeDescription()); @@ -3684,7 +3687,7 @@ void CppGenerator::finishGeneration() if (func->isSignal()) { foreach (AbstractMetaArgument* arg, func->arguments()) { if (arg->type()->isContainer()) { - QString value = translateType(arg->type(), metaClass); + QString value = translateType(arg->type(), metaClass, ExcludeConst); typeResolvers << QMetaObject::normalizedType(value.toAscii().constData()); } } From 1f28cdd2994f9a60e05ce887ad5568e3a9c648e9 Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Wed, 22 Dec 2010 14:58:37 -0300 Subject: [PATCH 189/564] Added support for promoting enums from removed namespaces to upper scope. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Classes in namespaces marked not to be generated are always moved to upper scopes, the current modification add this same behaviour to enums. Tests were also added. Reviewed by Lauro Moura Reviewed by Renato Araújo --- generator/cppgenerator.cpp | 42 +++++++++---- generator/headergenerator.cpp | 9 ++- generator/shibokengenerator.cpp | 32 ++++++++++ generator/shibokengenerator.h | 5 ++ tests/libsample/removednamespaces.h | 62 +++++++++++++++++++ tests/samplebinding/CMakeLists.txt | 1 + .../enumfromremovednamespace_test.py | 49 +++++++++++++++ tests/samplebinding/global.h | 1 + tests/samplebinding/typesystem_sample.xml | 15 +++++ 9 files changed, 201 insertions(+), 15 deletions(-) create mode 100644 tests/libsample/removednamespaces.h create mode 100644 tests/samplebinding/enumfromremovednamespace_test.py diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index de4c9234..cd5f3078 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -244,10 +244,14 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl } } + AbstractMetaEnumList classEnums = metaClass->enums(); + foreach (AbstractMetaClass* innerClass, metaClass->innerClasses()) + lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass); + //Extra includes s << endl << "// Extra includes" << endl; QList includes = metaClass->typeEntry()->extraIncludes(); - foreach (AbstractMetaEnum* cppEnum, metaClass->enums()) + foreach (AbstractMetaEnum* cppEnum, classEnums) includes.append(cppEnum->typeEntry()->extraIncludes()); qSort(includes.begin(), includes.end()); foreach (Include inc, includes) @@ -465,7 +469,7 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl writeTypeDiscoveryFunction(s, metaClass); - foreach (AbstractMetaEnum* cppEnum, metaClass->enums()) { + foreach (AbstractMetaEnum* cppEnum, classEnums) { if (cppEnum->isAnonymous() || cppEnum->isPrivate()) continue; @@ -2913,10 +2917,11 @@ void CppGenerator::writeMethodDefinition(QTextStream& s, const AbstractMetaFunct void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnum* cppEnum) { + const AbstractMetaClass* enclosingClass = getProperEnclosingClassForEnum(cppEnum); QString cpythonName = cpythonEnumName(cppEnum); QString addFunction; - if (cppEnum->enclosingClass()) - addFunction = "PyDict_SetItemString(" + cpythonTypeName(cppEnum->enclosingClass()) + ".super.ht_type.tp_dict,"; + if (enclosingClass) + addFunction = "PyDict_SetItemString(" + cpythonTypeName(enclosingClass) + ".super.ht_type.tp_dict,"; else if (cppEnum->isAnonymous()) addFunction = "PyModule_AddIntConstant(module,"; else @@ -2982,7 +2987,7 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu if (!cppEnum->isAnonymous()) { s << INDENT << "enumItem = Shiboken::Enum::newItem(" << cpythonName << "," << enumValueText; s << ", \"" << enumValue->name() << "\");" << endl; - } else if (cppEnum->enclosingClass()) { + } else if (enclosingClass) { s << INDENT << "enumItem = PyInt_FromLong(" << enumValueText << ");" << endl; shouldDecrefNumber = true; } else { @@ -3338,12 +3343,16 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m s << INDENT << "((PyObject*)&" << pyTypeName << "));" << endl << endl; } - if (!metaClass->enums().isEmpty()) { + AbstractMetaEnumList classEnums = metaClass->enums(); + foreach (AbstractMetaClass* innerClass, metaClass->innerClasses()) + lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass); + + if (!classEnums.isEmpty()) { s << INDENT << "// Initialize enums" << endl; s << INDENT << "PyObject* enumItem;" << endl << endl; } - foreach (const AbstractMetaEnum* cppEnum, metaClass->enums()) { + foreach (const AbstractMetaEnum* cppEnum, classEnums) { if (cppEnum->isPrivate()) continue; writeEnumInitialization(s, cppEnum); @@ -3544,10 +3553,19 @@ void CppGenerator::finishGeneration() s << include; s << endl; + // Global enums + AbstractMetaEnumList globalEnums = this->globalEnums(); + foreach (const AbstractMetaClass* metaClass, classes()) { + const AbstractMetaClass* encClass = metaClass->enclosingClass(); + if (encClass && encClass->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass) + continue; + lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass); + } + //Extra includes s << endl << "// Extra includes" << endl; QList includes; - foreach (AbstractMetaEnum* cppEnum, globalEnums()) + foreach (AbstractMetaEnum* cppEnum, globalEnums) includes.append(cppEnum->typeEntry()->extraIncludes()); qSort(includes.begin(), includes.end()); foreach (Include inc, includes) @@ -3577,13 +3595,13 @@ void CppGenerator::finishGeneration() s << "------------------------------------------------------------" << endl; s << classInitDecl << endl; - if (!globalEnums().isEmpty()) { + if (!globalEnums.isEmpty()) { QString converterImpl; QTextStream convImpl(&converterImpl); s << "// Enum definitions "; s << "------------------------------------------------------------" << endl; - foreach (const AbstractMetaEnum* cppEnum, globalEnums()) { + foreach (const AbstractMetaEnum* cppEnum, globalEnums) { if (cppEnum->isAnonymous() || cppEnum->isPrivate()) continue; s << endl; @@ -3661,12 +3679,12 @@ void CppGenerator::finishGeneration() } s << endl; - if (!globalEnums().isEmpty()) { + if (!globalEnums.isEmpty()) { s << INDENT << "// Initialize enums" << endl; s << INDENT << "PyObject* enumItem;" << endl << endl; } - foreach (const AbstractMetaEnum* cppEnum, globalEnums()) { + foreach (const AbstractMetaEnum* cppEnum, globalEnums) { if (cppEnum->isPrivate()) continue; writeEnumInitialization(s, cppEnum); diff --git a/generator/headergenerator.cpp b/generator/headergenerator.cpp index 7a49a8c4..9a28cdb9 100644 --- a/generator/headergenerator.cpp +++ b/generator/headergenerator.cpp @@ -311,9 +311,12 @@ void HeaderGenerator::finishGeneration() macrosStream << "// Type indices" << endl; int idx = 0; - foreach (const AbstractMetaClass* metaClass, classes()) + AbstractMetaEnumList globalEnums = this->globalEnums(); + foreach (const AbstractMetaClass* metaClass, classes()) { writeTypeIndexDefine(macrosStream, metaClass, idx); - foreach (const AbstractMetaEnum* metaEnum, globalEnums()) + lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass); + } + foreach (const AbstractMetaEnum* metaEnum, globalEnums) writeTypeIndexDefineLine(macrosStream, metaEnum->typeEntry(), idx); macrosStream << "#define "; macrosStream.setFieldWidth(60); @@ -324,7 +327,7 @@ void HeaderGenerator::finishGeneration() macrosStream << "extern PyTypeObject** " << cppApiVariableName() << ';' << endl << endl; macrosStream << "// Macros for type check" << endl; - foreach (const AbstractMetaEnum* cppEnum, globalEnums()) { + foreach (const AbstractMetaEnum* cppEnum, globalEnums) { if (cppEnum->isAnonymous() || cppEnum->isPrivate()) continue; includes << cppEnum->typeEntry()->include(); diff --git a/generator/shibokengenerator.cpp b/generator/shibokengenerator.cpp index 697c89e5..2647e634 100644 --- a/generator/shibokengenerator.cpp +++ b/generator/shibokengenerator.cpp @@ -216,6 +216,38 @@ bool ShibokenGenerator::shouldGenerateCppWrapper(const AbstractMetaClass* metaCl return result && !metaClass->isNamespace(); } +void ShibokenGenerator::lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumList& enumList, const AbstractMetaClass* metaClass) +{ + if (!metaClass) + return; + + if (metaClass->typeEntry()->codeGeneration() == TypeEntry::GenerateForSubclass) { + foreach (const AbstractMetaEnum* metaEnum, metaClass->enums()) { + if (metaEnum->isPrivate() || metaEnum->typeEntry()->codeGeneration() == TypeEntry::GenerateForSubclass) + continue; + if (!enumList.contains(const_cast(metaEnum))) + enumList.append(const_cast(metaEnum)); + } + lookForEnumsInClassesNotToBeGenerated(enumList, metaClass->enclosingClass()); + } +} + +static const AbstractMetaClass* getProperEnclosingClass(const AbstractMetaClass* metaClass) +{ + if (!metaClass) + return 0; + + if (metaClass->typeEntry()->codeGeneration() != TypeEntry::GenerateForSubclass) + return metaClass; + + return getProperEnclosingClass(metaClass->enclosingClass()); +} + +const AbstractMetaClass* ShibokenGenerator::getProperEnclosingClassForEnum(const AbstractMetaEnum* metaEnum) +{ + return getProperEnclosingClass(metaEnum->enclosingClass()); +} + QString ShibokenGenerator::wrapperName(const AbstractMetaClass* metaClass) { if (shouldGenerateCppWrapper(metaClass)) { diff --git a/generator/shibokengenerator.h b/generator/shibokengenerator.h index 74396eb0..ade04662 100644 --- a/generator/shibokengenerator.h +++ b/generator/shibokengenerator.h @@ -209,6 +209,11 @@ class ShibokenGenerator : public Generator /// Verifies if the class should have a C++ wrapper generated for it, instead of only a Python wrapper. static bool shouldGenerateCppWrapper(const AbstractMetaClass* metaClass); + /// Adds enums eligible for generation from classes/namespaces marked not to be generated. + static void lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumList& enumList, const AbstractMetaClass* metaClass); + /// Returns the enclosing class for an enum, or NULL if it should be global. + const AbstractMetaClass* getProperEnclosingClassForEnum(const AbstractMetaEnum* metaEnum); + static QString wrapperName(const AbstractMetaClass* metaClass); static QString fullPythonFunctionName(const AbstractMetaFunction* func); diff --git a/tests/libsample/removednamespaces.h b/tests/libsample/removednamespaces.h new file mode 100644 index 00000000..93c3fb80 --- /dev/null +++ b/tests/libsample/removednamespaces.h @@ -0,0 +1,62 @@ +/* + * This file is part of the Shiboken Python Binding Generator project. + * + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef REMOVEDNAMESPACE_H +#define REMOVEDNAMESPACE_H + +#include "libsamplemacros.h" + +namespace RemovedNamespace1 +{ + +enum RemovedNamespace1_Enum { + RemovedNamespace1_Enum_Value0 +}; + +enum { + RemovedNamespace1_AnonymousEnum_Value0 +}; + +namespace RemovedNamespace2 { + enum RemovedNamespace2_Enum { + RemovedNamespace2_Enum_Value0 + }; +} + +} + +namespace UnremovedNamespace +{ +namespace RemovedNamespace3 +{ + enum RemovedNamespace3_Enum { + RemovedNamespace3_Enum_Value0 + }; + + enum { + RemovedNamespace3_AnonymousEnum_Value0 + }; +} +} + +#endif // REMOVEDNAMESPACE_H + diff --git a/tests/samplebinding/CMakeLists.txt b/tests/samplebinding/CMakeLists.txt index 052e246a..8e7daf3c 100644 --- a/tests/samplebinding/CMakeLists.txt +++ b/tests/samplebinding/CMakeLists.txt @@ -76,6 +76,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/sonofmderived1_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/str_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/strlist_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/time_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/unremovednamespace_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/virtualdaughter_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/virtualdtor_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/virtualmethods_wrapper.cpp diff --git a/tests/samplebinding/enumfromremovednamespace_test.py b/tests/samplebinding/enumfromremovednamespace_test.py new file mode 100644 index 00000000..4fd29582 --- /dev/null +++ b/tests/samplebinding/enumfromremovednamespace_test.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python + +# -*- coding: utf-8 -*- +# +# This file is part of the Shiboken Python Bindings Generator project. +# +# Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +# +# Contact: PySide team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# version 2.1 as published by the Free Software Foundation. Please +# review the following information to ensure the GNU Lesser General +# Public License version 2.1 requirements will be met: +# http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +# # +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +import unittest + +import sample + +class TestEnumFromRemovedNamespace(unittest.TestCase): + def testEnumPromotedToGlobal(self): + sample.RemovedNamespace1_Enum + sample.RemovedNamespace1_Enum_Value0 + sample.RemovedNamespace1_AnonymousEnum_Value0 + sample.RemovedNamespace2_Enum + sample.RemovedNamespace2_Enum_Value0 + + def testEnumPromotedToUpperNamespace(self): + sample.UnremovedNamespace + sample.UnremovedNamespace.RemovedNamespace3_Enum + sample.UnremovedNamespace.RemovedNamespace3_Enum_Value0 + sample.UnremovedNamespace.RemovedNamespace3_AnonymousEnum_Value0 + + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/samplebinding/global.h b/tests/samplebinding/global.h index 90cae083..95094f7d 100644 --- a/tests/samplebinding/global.h +++ b/tests/samplebinding/global.h @@ -36,6 +36,7 @@ #include "privatedtor.h" #include "protected.h" #include "reference.h" +#include "removednamespaces.h" #include "samplenamespace.h" #include "simplefile.h" #include "size.h" diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index ae6f61b9..67956bc0 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -124,6 +124,21 @@ + + + + + + + + + + + + + + + From 1f2cc5e621431e4a7bb0126b83c768489b9e11c0 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Thu, 23 Dec 2010 10:50:34 -0300 Subject: [PATCH 190/564] Removed '&' from type registration. Reviewer: Lauro Mora Marcelo Lira --- generator/cppgenerator.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index cd5f3078..9bace889 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -3055,9 +3055,9 @@ void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaC if ((cppSignature != originalSignature) && !knowTypes.contains(originalSignature)) { knowTypes << originalSignature; - Options opt = NoOption; + Options opt = ExcludeReference; if (type->isContainer()) - opt = ExcludeConst; + opt |= ExcludeConst; s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver<" << translateType(type, metaClass, opt) << " >" << "(\"" << skipNamespace(originalSignature) << "\"); // " << type->cppSignature() << "\n"; @@ -3705,7 +3705,7 @@ void CppGenerator::finishGeneration() if (func->isSignal()) { foreach (AbstractMetaArgument* arg, func->arguments()) { if (arg->type()->isContainer()) { - QString value = translateType(arg->type(), metaClass, ExcludeConst); + QString value = translateType(arg->type(), metaClass, ExcludeConst | ExcludeReference); typeResolvers << QMetaObject::normalizedType(value.toAscii().constData()); } } From b671bda382fc85954a3587dbe728baa728dfe567 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Thu, 23 Dec 2010 14:40:50 -0300 Subject: [PATCH 191/564] Used Qt4.7 code to normalize types for all previous Qt version. Reviewer: Lauro Moura Hugo Parente Lima --- generator/CMakeLists.txt | 1 + generator/cppgenerator.cpp | 13 +- generator/shibokennormalize.cpp | 274 ++++++++++++++++++++++++++++++++ generator/shibokennormalize_p.h | 41 +++++ 4 files changed, 323 insertions(+), 6 deletions(-) create mode 100644 generator/shibokennormalize.cpp create mode 100644 generator/shibokennormalize_p.h diff --git a/generator/CMakeLists.txt b/generator/CMakeLists.txt index 89b2ef75..1a2eb1f0 100644 --- a/generator/CMakeLists.txt +++ b/generator/CMakeLists.txt @@ -6,6 +6,7 @@ headergenerator.cpp overloaddata.cpp shiboken.cpp shibokengenerator.cpp +shibokennormalize.cpp ) include_directories(${CMAKE_CURRENT_SOURCE_DIR} diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 9bace889..cbfa5ffc 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -22,6 +22,7 @@ */ #include "cppgenerator.h" +#include "shibokennormalize_p.h" #include #include @@ -3043,11 +3044,11 @@ void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaC AbstractMetaArgument *a = cppSignal->arguments().at(i); AbstractMetaType* type = a->type(); - QString cppSignature = QMetaObject::normalizedType(qPrintable(type->cppSignature())); - QString originalSignature = QMetaObject::normalizedType(qPrintable(type->originalTypeDescription())); + QString cppSignature = SBK_NORMALIZED_TYPE(qPrintable(type->cppSignature())); + QString originalSignature = SBK_NORMALIZED_TYPE(qPrintable(type->originalTypeDescription())); if (!a->defaultValueExpression().isEmpty()) { - QString sig = QMetaObject::normalizedSignature(signature.toAscii()); + QString sig = SBK_NORMALIZED_SIGNATURE(signature.toAscii()); if (sig.isEmpty()) sig = "void"; signatures[cppSignal->name()].append(sig); @@ -3062,12 +3063,12 @@ void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaC << translateType(type, metaClass, opt) << " >" << "(\"" << skipNamespace(originalSignature) << "\"); // " << type->cppSignature() << "\n"; } - signature += skipNamespace(type->originalTypeDescription()); + signature += SBK_NORMALIZED_TYPE(skipNamespace(type->originalTypeDescription()).toAscii()); } } else { signature = "void"; } - signatures[cppSignal->name()].append(QMetaObject::normalizedSignature(signature.toAscii())); + signatures[cppSignal->name()].append(SBK_NORMALIZED_SIGNATURE(signature.toAscii())); } } @@ -3706,7 +3707,7 @@ void CppGenerator::finishGeneration() foreach (AbstractMetaArgument* arg, func->arguments()) { if (arg->type()->isContainer()) { QString value = translateType(arg->type(), metaClass, ExcludeConst | ExcludeReference); - typeResolvers << QMetaObject::normalizedType(value.toAscii().constData()); + typeResolvers << SBK_NORMALIZED_TYPE(value.toAscii().constData()); } } } diff --git a/generator/shibokennormalize.cpp b/generator/shibokennormalize.cpp new file mode 100644 index 00000000..01aad973 --- /dev/null +++ b/generator/shibokennormalize.cpp @@ -0,0 +1,274 @@ +/* + * This file is part of the PySide project. + * This code was extracted from qmetaobject_p.h present on Qt4.7. + * + * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "shibokennormalize_p.h" +#include + +#if (QT_VERSION < QT_VERSION_CHECK(4, 7, 0)) + +// mirrored in moc's utils.h +static inline bool is_ident_char(char s) +{ + return ((s >= 'a' && s <= 'z') + || (s >= 'A' && s <= 'Z') + || (s >= '0' && s <= '9') + || s == '_' + ); +} + +static inline bool is_space(char s) +{ + return (s == ' ' || s == '\t'); +} + +static void qRemoveWhitespace(const char *s, char *d) +{ + char last = 0; + while (*s && is_space(*s)) + s++; + while (*s) { + while (*s && !is_space(*s)) + last = *d++ = *s++; + while (*s && is_space(*s)) + s++; + if (*s && ((is_ident_char(*s) && is_ident_char(last)) + || ((*s == ':') && (last == '<')))) { + last = *d++ = ' '; + } + } + *d = '\0'; +} + +// This code is shared with moc.cpp +static QByteArray normalizeTypeInternalQt47(const char *t, const char *e, bool fixScope = false, bool adjustConst = true) +{ + int len = e - t; + /* + Convert 'char const *' into 'const char *'. Start at index 1, + not 0, because 'const char *' is already OK. + */ + QByteArray constbuf; + for (int i = 1; i < len; i++) { + if ( t[i] == 'c' + && strncmp(t + i + 1, "onst", 4) == 0 + && (i + 5 >= len || !is_ident_char(t[i + 5])) + && !is_ident_char(t[i-1]) + ) { + constbuf = QByteArray(t, len); + if (is_space(t[i-1])) + constbuf.remove(i-1, 6); + else + constbuf.remove(i, 5); + constbuf.prepend("const "); + t = constbuf.data(); + e = constbuf.data() + constbuf.length(); + break; + } + /* + We musn't convert 'char * const *' into 'const char **' + and we must beware of 'Bar'. + */ + if (t[i] == '&' || t[i] == '*' ||t[i] == '<') + break; + } + if (adjustConst && e > t + 6 && strncmp("const ", t, 6) == 0) { + if (*(e-1) == '&') { // treat const reference as value + t += 6; + --e; + } else if (is_ident_char(*(e-1)) || *(e-1) == '>') { // treat const value as value + t += 6; + } + } + QByteArray result; + result.reserve(len); + +#if 1 + // consume initial 'const ' + if (strncmp("const ", t, 6) == 0) { + t+= 6; + result += "const "; + } +#endif + + // some type substitutions for 'unsigned x' + if (strncmp("unsigned", t, 8) == 0) { + // make sure "unsigned" is an isolated word before making substitutions + if (!t[8] || !is_ident_char(t[8])) { + if (strncmp(" int", t+8, 4) == 0) { + t += 8+4; + result += "uint"; + } else if (strncmp(" long", t+8, 5) == 0) { + if ((strlen(t + 8 + 5) < 4 || strncmp(t + 8 + 5, " int", 4) != 0) // preserve '[unsigned] long int' + && (strlen(t + 8 + 5) < 5 || strncmp(t + 8 + 5, " long", 5) != 0) // preserve '[unsigned] long long' + ) { + t += 8+5; + result += "ulong"; + } + } else if (strncmp(" short", t+8, 6) != 0 // preserve unsigned short + && strncmp(" char", t+8, 5) != 0) { // preserve unsigned char + // treat rest (unsigned) as uint + t += 8; + result += "uint"; + } + } + } else { + // discard 'struct', 'class', and 'enum'; they are optional + // and we don't want them in the normalized signature + struct { + const char *keyword; + int len; + } optional[] = { + { "struct ", 7 }, + { "class ", 6 }, + { "enum ", 5 }, + { 0, 0 } + }; + int i = 0; + do { + if (strncmp(optional[i].keyword, t, optional[i].len) == 0) { + t += optional[i].len; + break; + } + } while (optional[++i].keyword != 0); + } + + bool star = false; + while (t != e) { + char c = *t++; + if (fixScope && c == ':' && *t == ':' ) { + ++t; + c = *t++; + int i = result.size() - 1; + while (i >= 0 && is_ident_char(result.at(i))) + --i; + result.resize(i + 1); + } + star = star || c == '*'; + result += c; + if (c == '<') { + //template recursion + const char* tt = t; + int templdepth = 1; + while (t != e) { + c = *t++; + if (c == '<') + ++templdepth; + if (c == '>') + --templdepth; + if (templdepth == 0 || (templdepth == 1 && c == ',')) { + result += normalizeTypeInternalQt47(tt, t-1, fixScope, false); + result += c; + if (templdepth == 0) { + if (*t == '>') + result += ' '; // avoid >> + break; + } + tt = t; + } + } + } + + // cv qualifers can appear after the type as well + if (!is_ident_char(c) && t != e && (e - t >= 5 && strncmp("const", t, 5) == 0) + && (e - t == 5 || !is_ident_char(t[5]))) { + t += 5; + while (t != e && is_space(*t)) + ++t; + if (adjustConst && t != e && *t == '&') { + // treat const ref as value + ++t; + } else if (adjustConst && !star) { + // treat const as value + } else if (!star) { + // move const to the front (but not if const comes after a *) + result.prepend("const "); + } else { + // keep const after a * + result += "const"; + } + } + } + + return result; +} + +static char *qNormalizeTypeQt47(char *d, int &templdepth, QByteArray &result) +{ + const char *t = d; + while (*d && (templdepth + || (*d != ',' && *d != ')'))) { + if (*d == '<') + ++templdepth; + if (*d == '>') + --templdepth; + ++d; + } + if (strncmp("void", t, d - t) != 0) + result += normalizeTypeInternalQt47(t, d); + + return d; +} + + +QByteArray QMetaObject_normalizedTypeQt47(const char *type) +{ + QByteArray result; + + if (!type || !*type) + return result; + + QVarLengthArray stackbuf(qstrlen(type) + 1); + qRemoveWhitespace(type, stackbuf.data()); + int templdepth = 0; + qNormalizeTypeQt47(stackbuf.data(), templdepth, result); + + return result; +} + +QByteArray QMetaObject_normalizedSignatureQt47(const char *method) +{ + QByteArray result; + if (!method || !*method) + return result; + int len = int(strlen(method)); + QVarLengthArray stackbuf(len + 1); + char *d = stackbuf.data(); + qRemoveWhitespace(method, d); + + result.reserve(len); + + int argdepth = 0; + int templdepth = 0; + while (*d) { + if (argdepth == 1) + d = qNormalizeTypeQt47(d, templdepth, result); + if (*d == '(') + ++argdepth; + if (*d == ')') + --argdepth; + result += *d++; + } + + return result; +} +#endif diff --git a/generator/shibokennormalize_p.h b/generator/shibokennormalize_p.h new file mode 100644 index 00000000..0a55b507 --- /dev/null +++ b/generator/shibokennormalize_p.h @@ -0,0 +1,41 @@ +/* + * This file is part of the PySide project. + * + * Copyright (C) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SHIBOKENNORMALIZE_P_H +#define SHIBOKENNORMALIZE_P_H + +#include +#include + + +#if (QT_VERSION < QT_VERSION_CHECK(4, 7, 0)) + QByteArray QMetaObject_normalizedTypeQt47(const char *type); + QByteArray QMetaObject_normalizedSignatureQt47(const char *type); + + #define SBK_NORMALIZED_TYPE(x) QMetaObject_normalizedTypeQt47(x) + #define SBK_NORMALIZED_SIGNATURE(x) QMetaObject_normalizedSignatureQt47(x) +#else + #define SBK_NORMALIZED_TYPE(x) QMetaObject::normalizedType(x) + #define SBK_NORMALIZED_SIGNATURE(x) QMetaObject::normalizedSignature(x) +#endif + +#endif //SHIBOKENNORMALIZE_P_H From fc997ef702dfe2d40b8420a3c98ca16d9d276596 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Thu, 23 Dec 2010 15:50:54 -0200 Subject: [PATCH 192/564] Fix bug#554 - "Inner classes don't work and give us a segfault" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Marcelo Lira Renato Araújo --- libshiboken/basewrapper.cpp | 7 +++-- tests/samplebinding/bug_554_test.py | 40 +++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 tests/samplebinding/bug_554_test.py diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index ba26c965..8c0c2886 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -186,7 +186,7 @@ void SbkDeallocWrapperWithPrivateDtor(PyObject* self) void SbkObjectTypeDealloc(PyObject* pyObj) { - SbkObjectType* sbkType = reinterpret_cast(pyObj->ob_type); + SbkObjectType* sbkType = reinterpret_cast(pyObj); if (!sbkType->d) return; @@ -208,8 +208,8 @@ PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* k if (!newType) return 0; - SbkObjectTypePrivate* d = new SbkObjectTypePrivate; - memset(d, 0, sizeof(SbkObjectTypePrivate)); + Shiboken::ObjectType::initPrivateData(newType); + SbkObjectTypePrivate* d = newType->d; std::list bases = Shiboken::getCppBaseClasses(reinterpret_cast(newType)); if (bases.size() == 1) { @@ -239,7 +239,6 @@ PyObject* SbkObjectTypeTpNew(PyTypeObject* metatype, PyObject* args, PyObject* k d->user_data = 0; d->d_func = 0; d->is_user_type = 1; - newType->d = d; std::list::const_iterator it = bases.begin(); for (; it != bases.end(); ++it) { diff --git a/tests/samplebinding/bug_554_test.py b/tests/samplebinding/bug_554_test.py new file mode 100644 index 00000000..16d9a9c0 --- /dev/null +++ b/tests/samplebinding/bug_554_test.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# This file is part of the Shiboken Python Bindings Generator project. +# +# Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +# +# Contact: PySide team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# version 2.1 as published by the Free Software Foundation. Please +# review the following information to ensure the GNU Lesser General +# Public License version 2.1 requirements will be met: +# http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +# # +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +'''Unit test for bug#554''' + +from sample import * + +class Bug554: + def crash(self): + class Crasher(ObjectType): + pass + +if __name__ == '__main__': + bug = Bug554() + bug.crash() + + From e9f833b5a2d4ce4893bdbfe844f224a1cd689d6a Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 28 Dec 2010 15:03:10 -0200 Subject: [PATCH 193/564] Fix typo --- tests/libsample/objecttype.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/libsample/objecttype.h b/tests/libsample/objecttype.h index bb7787e4..1eeb4c60 100644 --- a/tests/libsample/objecttype.h +++ b/tests/libsample/objecttype.h @@ -97,7 +97,7 @@ class LIBSAMPLE_API ObjectType void setObjectNameWithSize(const char*, int size=9, const Str& name = Str("")); void setObjectNameWithSize(const Str& name = Str(""), int size=9); - //Function used to comfuse the generator when two values accept Null as arg + //Function used to confuse the generator when two values accept Null as arg void setObject(ObjectType *); void setObject(const Null&); int callId() const; From 5bfe40a435b49cf23aac247d1f6336def879ee71 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 28 Dec 2010 17:24:18 -0200 Subject: [PATCH 194/564] Avoid compiler warning about unhandled constant in switch block. --- tests/libsample/expression.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/libsample/expression.cpp b/tests/libsample/expression.cpp index d93d47f0..f6eedaa7 100644 --- a/tests/libsample/expression.cpp +++ b/tests/libsample/expression.cpp @@ -118,6 +118,9 @@ std::string Expression::toString() const case GreaterThan: op = '<'; break; + case None: // just to avoid the compiler warning + default: + break; } result += op; result += m_operand2->toString(); From 670b96db4dd58dc4e265a5e49439f705bb6193c1 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 28 Dec 2010 15:24:11 -0200 Subject: [PATCH 195/564] Fix bug#495 - "Broken rich compare operators if they use an object-type as parameter" --- generator/cppgenerator.cpp | 24 ++++++--- tests/libsample/CMakeLists.txt | 1 + tests/libsample/objecttypeoperators.cpp | 43 ++++++++++++++++ tests/libsample/objecttypeoperators.h | 50 +++++++++++++++++++ tests/samplebinding/CMakeLists.txt | 1 + tests/samplebinding/global.h | 1 + .../samplebinding/objecttypeoperators_test.py | 43 ++++++++++++++++ tests/samplebinding/typesystem_sample.xml | 2 + 8 files changed, 158 insertions(+), 7 deletions(-) create mode 100644 tests/libsample/objecttypeoperators.cpp create mode 100644 tests/libsample/objecttypeoperators.h create mode 100644 tests/samplebinding/objecttypeoperators_test.py diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index cbfa5ffc..7f6ae27b 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -531,6 +531,8 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu const TypeEntry* type = func->type() ? func->type()->typeEntry() : 0; + const QString funcName = func->isOperatorOverload() ? pythonOperatorFunctionName(func) : func->name(); + QString prefix = wrapperName(func->ownerClass()) + "::"; s << functionSignature(func, prefix, "", Generator::SkipDefaultValues|Generator::OriginalTypeDescription) << endl; s << "{" << endl; @@ -582,7 +584,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu s << INDENT << "Shiboken::GilState gil;" << endl; s << INDENT << "Shiboken::AutoDecRef py_override(Shiboken::BindingManager::instance().getOverride(this, \""; - s << func->name() << "\"));" << endl; + s << funcName << "\"));" << endl; s << INDENT << "if (py_override.isNull()) {" << endl; { @@ -597,7 +599,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu if (func->isAbstract()) { s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"pure virtual method '"; - s << func->ownerClass()->name() << '.' << func->name(); + s << func->ownerClass()->name() << '.' << funcName; s << "()' not implemented.\");" << endl; s << INDENT << "return "; if (func->type()) { @@ -751,7 +753,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu { Indentation indent(INDENT); s << INDENT << "PyErr_Format(PyExc_TypeError, \"Invalid return value in function %s, expected %s, got %s.\", \"" - << func->ownerClass()->name() << '.' << func->name() << "\", " << desiredType + << func->ownerClass()->name() << '.' << funcName << "\", " << desiredType << ", " PYTHON_RETURN_VAR "->ob_type->tp_name);" << endl; s << INDENT << "return " << defaultReturnExpr << ';' << endl; } @@ -2838,14 +2840,22 @@ void CppGenerator::writeRichCompareFunction(QTextStream& s, const AbstractMetaCl Indentation indent(INDENT); s << INDENT << "// " << func->signature() << endl; s << INDENT; - s << translateTypeForWrapperMethod(type, metaClass, ExcludeReference | ExcludeConst); + s << translateTypeForWrapperMethod(type, 0, ExcludeReference | ExcludeConst); + if (type->isObject() || type->isQObject()) + s << '&'; s << " cppOther = "; - writeToCppConversion(s, type, metaClass, "other", ExcludeReference | ExcludeConst); + writeToCppConversion(s, type, 0, "other", ExcludeReference | ExcludeConst); s << ';' << endl; s << INDENT << "result = "; - writeToPythonConversion(s, func->type(), metaClass, CPP_SELF_VAR " " + op + " cppOther"); - s << ';' << endl; + if (!func->type()) { + s << "Py_None;" << endl; + s << INDENT << "Py_INCREF(Py_None);" << endl; + s << INDENT << CPP_SELF_VAR " " << op << " cppOther; // this op return void" << endl; + } else { + writeToPythonConversion(s, func->type(), metaClass, CPP_SELF_VAR " " + op + " cppOther"); + s << ';' << endl; + } } s << INDENT << '}'; } diff --git a/tests/libsample/CMakeLists.txt b/tests/libsample/CMakeLists.txt index b6cd1b92..e1abe6a9 100644 --- a/tests/libsample/CMakeLists.txt +++ b/tests/libsample/CMakeLists.txt @@ -19,6 +19,7 @@ multiple_derived.cpp objectmodel.cpp objecttype.cpp objecttypelayout.cpp +objecttypeoperators.cpp objectview.cpp overload.cpp overloadsort.cpp diff --git a/tests/libsample/objecttypeoperators.cpp b/tests/libsample/objecttypeoperators.cpp new file mode 100644 index 00000000..08c49b1a --- /dev/null +++ b/tests/libsample/objecttypeoperators.cpp @@ -0,0 +1,43 @@ +/* + * This file is part of the Shiboken Python Binding Generator project. + * + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "objecttypeoperators.h" + +ObjectTypeOperators::ObjectTypeOperators(const std::string key) : m_key(key) +{ +} + +bool ObjectTypeOperators::operator==(const ObjectTypeOperators& other) const +{ + return m_key == other.m_key; +} + +bool ObjectTypeOperators::operator==(const std::string& other) const +{ + return m_key == other; +} + +const ObjectTypeOperators& ObjectTypeOperators::operator<(const ObjectTypeOperators& other) const +{ + return m_key < other.m_key ? *this : other; +} + diff --git a/tests/libsample/objecttypeoperators.h b/tests/libsample/objecttypeoperators.h new file mode 100644 index 00000000..1d65eb16 --- /dev/null +++ b/tests/libsample/objecttypeoperators.h @@ -0,0 +1,50 @@ +/* + * This file is part of the Shiboken Python Binding Generator project. + * + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef OBJECTTYPEOPERATORS_H +#define OBJECTTYPEOPERATORS_H + +#include "libsamplemacros.h" +#include + +class LIBSAMPLE_API ObjectTypeOperators +{ +public: + ObjectTypeOperators(const std::string key); + + bool operator==(const ObjectTypeOperators& other) const; + bool operator==(const std::string& other) const; + const ObjectTypeOperators& operator<(const ObjectTypeOperators& other) const; + + // chaos! + virtual void operator>(const ObjectTypeOperators&) { m_key.append("operator>"); } + + std::string key() const { return m_key; } + +private: + std::string m_key; + + ObjectTypeOperators(ObjectTypeOperators&); + ObjectTypeOperators& operator=(ObjectTypeOperators&); +}; + +#endif // OBJECTTYPEOPERATORS_H diff --git a/tests/samplebinding/CMakeLists.txt b/tests/samplebinding/CMakeLists.txt index 8e7daf3c..1fa95501 100644 --- a/tests/samplebinding/CMakeLists.txt +++ b/tests/samplebinding/CMakeLists.txt @@ -45,6 +45,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/nondefaultctor_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/objectmodel_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/objecttype_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/objecttypelayout_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/objecttypeoperators_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/objectview_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/objtypereference_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/oddbooluser_wrapper.cpp diff --git a/tests/samplebinding/global.h b/tests/samplebinding/global.h index 95094f7d..181ed29f 100644 --- a/tests/samplebinding/global.h +++ b/tests/samplebinding/global.h @@ -24,6 +24,7 @@ #include "objecttype.h" #include "objecttypelayout.h" #include "objecttypereference.h" +#include "objecttypeoperators.h" #include "objectview.h" #include "oddbool.h" #include "overload.h" diff --git a/tests/samplebinding/objecttypeoperators_test.py b/tests/samplebinding/objecttypeoperators_test.py new file mode 100644 index 00000000..d03c9bc4 --- /dev/null +++ b/tests/samplebinding/objecttypeoperators_test.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# This file is part of the Shiboken Python Bindings Generator project. +# +# Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +# +# Contact: PySide team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# version 2.1 as published by the Free Software Foundation. Please +# review the following information to ensure the GNU Lesser General +# Public License version 2.1 requirements will be met: +# http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +# # +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +import unittest +from sample import * + +class ObjectTypeOperatorsTest(unittest.TestCase): + + def testIt(self): + a = ObjectTypeOperators("a") + b = ObjectTypeOperators("b") + self.assertFalse(a == b) + self.assertEqual(a, a < b) + + # this should change a.key() and return nothing. + self.assertEqual(None, a > b) + self.assertEqual(a.key(), "aoperator>") + +if __name__ == '__main__': + unittest.main() diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 67956bc0..576c5465 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -1274,6 +1274,8 @@ + + From a4d79ddbac83e4b3338dfc5061765f0967f1fcc5 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 29 Dec 2010 08:55:46 -0200 Subject: [PATCH 196/564] Don't generate type resolvers using the const keyword. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Renato Araújo Marcelo Lira --- generator/cppgenerator.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 7f6ae27b..2829729c 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -3066,11 +3066,8 @@ void CppGenerator::writeSignalInitialization(QTextStream& s, const AbstractMetaC if ((cppSignature != originalSignature) && !knowTypes.contains(originalSignature)) { knowTypes << originalSignature; - Options opt = ExcludeReference; - if (type->isContainer()) - opt |= ExcludeConst; s << INDENT << "Shiboken::TypeResolver::createValueTypeResolver<" - << translateType(type, metaClass, opt) << " >" + << translateType(type, metaClass, ExcludeReference | ExcludeConst) << " >" << "(\"" << skipNamespace(originalSignature) << "\"); // " << type->cppSignature() << "\n"; } signature += SBK_NORMALIZED_TYPE(skipNamespace(type->originalTypeDescription()).toAscii()); From 6d0f92a096f0e81fa2e3b219cc38e90821d01b51 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 29 Dec 2010 10:55:43 -0200 Subject: [PATCH 197/564] Put __file__ on argv only when a empty list is given. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Marcelo Lira Renato Araújo --- libshiboken/helper.cpp | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/libshiboken/helper.cpp b/libshiboken/helper.cpp index 50bf6941..7359acf0 100644 --- a/libshiboken/helper.cpp +++ b/libshiboken/helper.cpp @@ -42,24 +42,32 @@ bool sequenceToArgcArgv(PyObject* argList, int* argc, char*** argv, const char* return false; } - *argc = numArgs + 1; + bool hasEmptyArgList = numArgs == 0; + if (hasEmptyArgList) + numArgs = 1; + + *argc = numArgs; *argv = new char*[*argc]; - for (int i = 0; i < numArgs; ++i) { - PyObject* item = PySequence_Fast_GET_ITEM(args.object(), i); - char* string; - if (PyUnicode_Check(item)) { - Shiboken::AutoDecRef utf8(PyUnicode_AsUTF8String(item)); - string = strdup(PyString_AS_STRING(utf8.object())); - } else { - string = strdup(PyString_AS_STRING(item)); + + if (hasEmptyArgList) { + // Try to get the script name + PyObject* globals = PyEval_GetGlobals(); + PyObject* appName = PyDict_GetItemString(globals, "__file__"); + (*argv)[0] = strdup(appName ? PyString_AS_STRING(appName) : defaultAppName); + } else { + for (int i = 0; i < numArgs; ++i) { + PyObject* item = PySequence_Fast_GET_ITEM(args.object(), i); + char* string; + if (PyUnicode_Check(item)) { + Shiboken::AutoDecRef utf8(PyUnicode_AsUTF8String(item)); + string = strdup(PyString_AS_STRING(utf8.object())); + } else { + string = strdup(PyString_AS_STRING(item)); + } + (*argv)[i] = string; } - (*argv)[i+1] = string; } - // Try to get the script name - PyObject* globals = PyEval_GetGlobals(); - PyObject* appName = PyDict_GetItemString(globals, "__file__"); - (*argv)[0] = strdup(appName ? PyString_AS_STRING(appName) : defaultAppName); return true; } From e5da714a34ea4571573741a79f0733c561f1c13d Mon Sep 17 00:00:00 2001 From: Lauro Neto Date: Wed, 29 Dec 2010 15:39:46 -0300 Subject: [PATCH 198/564] Fix test after changes to SequenceToArgcArgv Reviewer: Marcelo Lira Reviewer: Hugo Lima --- tests/libsample/injectcode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/libsample/injectcode.cpp b/tests/libsample/injectcode.cpp index 6e19de75..05c4a143 100644 --- a/tests/libsample/injectcode.cpp +++ b/tests/libsample/injectcode.cpp @@ -54,7 +54,7 @@ const char* InjectCode::simpleMethod2() const char* InjectCode::simpleMethod3(int argc, char** argv) { - for (int i = 1; i < argc; ++i) + for (int i = 0; i < argc; ++i) m_valueHolder += argv[i]; return m_valueHolder.c_str(); } From 1faf14ceb8a3eff5ecf3b92ce846970171f9e2b8 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 29 Dec 2010 16:34:39 -0200 Subject: [PATCH 199/564] Add support to fix the bug#493 - "__eq__ and friends not implemented for QKeyEvent == QKeySequence" --- generator/cppgenerator.cpp | 8 ++++++- tests/libsample/objecttypeoperators.cpp | 22 +++++++++++++++---- tests/libsample/objecttypeoperators.h | 8 +++++-- .../samplebinding/objecttypeoperators_test.py | 9 ++++++++ 4 files changed, 40 insertions(+), 7 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 2829729c..47a2ca2c 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2013,6 +2013,9 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f } } else if (func->isOperatorOverload()) { QString firstArg("(*" CPP_SELF_VAR ")"); + if (func->isPointerOperator()) + firstArg.remove(1, 1); // remove the de-reference operator + QString secondArg(CPP_ARG0); if (!func->isUnaryOperator() && shouldDereferenceArgumentPointer(func->arguments().first())) { secondArg.prepend('('); @@ -2853,7 +2856,10 @@ void CppGenerator::writeRichCompareFunction(QTextStream& s, const AbstractMetaCl s << INDENT << "Py_INCREF(Py_None);" << endl; s << INDENT << CPP_SELF_VAR " " << op << " cppOther; // this op return void" << endl; } else { - writeToPythonConversion(s, func->type(), metaClass, CPP_SELF_VAR " " + op + " cppOther"); + QByteArray self(CPP_SELF_VAR); + if (func->isPointerOperator()) + self.prepend('&'); + writeToPythonConversion(s, func->type(), metaClass, self + ' ' + op + " cppOther"); s << ';' << endl; } } diff --git a/tests/libsample/objecttypeoperators.cpp b/tests/libsample/objecttypeoperators.cpp index 08c49b1a..43aedc5d 100644 --- a/tests/libsample/objecttypeoperators.cpp +++ b/tests/libsample/objecttypeoperators.cpp @@ -31,13 +31,27 @@ bool ObjectTypeOperators::operator==(const ObjectTypeOperators& other) const return m_key == other.m_key; } -bool ObjectTypeOperators::operator==(const std::string& other) const +const ObjectTypeOperators& ObjectTypeOperators::operator<(const ObjectTypeOperators& other) const { - return m_key == other; + return m_key < other.m_key ? *this : other; } -const ObjectTypeOperators& ObjectTypeOperators::operator<(const ObjectTypeOperators& other) const +bool operator==(const ObjectTypeOperators* obj, const std::string& str) { - return m_key < other.m_key ? *this : other; + return obj->key() == str; +} + +bool operator==(const std::string& str, const ObjectTypeOperators* obj) +{ + return str == obj->key(); +} + +std::string operator+(const ObjectTypeOperators* obj, const std::string& str) +{ + return obj->key() + str; } +std::string operator+(const std::string& str, const ObjectTypeOperators* obj) +{ + return str + obj->key(); +} diff --git a/tests/libsample/objecttypeoperators.h b/tests/libsample/objecttypeoperators.h index 1d65eb16..9c1a85dc 100644 --- a/tests/libsample/objecttypeoperators.h +++ b/tests/libsample/objecttypeoperators.h @@ -29,10 +29,9 @@ class LIBSAMPLE_API ObjectTypeOperators { public: - ObjectTypeOperators(const std::string key); + explicit ObjectTypeOperators(const std::string key); bool operator==(const ObjectTypeOperators& other) const; - bool operator==(const std::string& other) const; const ObjectTypeOperators& operator<(const ObjectTypeOperators& other) const; // chaos! @@ -47,4 +46,9 @@ class LIBSAMPLE_API ObjectTypeOperators ObjectTypeOperators& operator=(ObjectTypeOperators&); }; +LIBSAMPLE_API bool operator==(const ObjectTypeOperators* obj, const std::string& str); +LIBSAMPLE_API bool operator==(const std::string& str, const ObjectTypeOperators* obj); +LIBSAMPLE_API std::string operator+(const ObjectTypeOperators* obj, const std::string& str); +LIBSAMPLE_API std::string operator+(const std::string& str, const ObjectTypeOperators* obj); + #endif // OBJECTTYPEOPERATORS_H diff --git a/tests/samplebinding/objecttypeoperators_test.py b/tests/samplebinding/objecttypeoperators_test.py index d03c9bc4..148bc359 100644 --- a/tests/samplebinding/objecttypeoperators_test.py +++ b/tests/samplebinding/objecttypeoperators_test.py @@ -39,5 +39,14 @@ def testIt(self): self.assertEqual(None, a > b) self.assertEqual(a.key(), "aoperator>") + def testPointerOpeators(self): + a = ObjectTypeOperators("a") + b = ObjectTypeOperators("b") + self.assertEqual(a + "bc", "abc") + self.assertEqual("bc" + a, "bca") + self.assertEqual("a", a) + self.assertEqual(a, "a") + + if __name__ == '__main__': unittest.main() From 304a8d46c162a3289da16ebcef839ff5c1b8697c Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 29 Dec 2010 16:42:38 -0200 Subject: [PATCH 200/564] Use QByteArray instead of QString to save 1 pico second :-) --- generator/cppgenerator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 47a2ca2c..5980fdad 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2012,11 +2012,11 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f + "\" with the modifications described in the type system file"), NULL); } } else if (func->isOperatorOverload()) { - QString firstArg("(*" CPP_SELF_VAR ")"); + QByteArray firstArg("(*" CPP_SELF_VAR ")"); if (func->isPointerOperator()) firstArg.remove(1, 1); // remove the de-reference operator - QString secondArg(CPP_ARG0); + QByteArray secondArg(CPP_ARG0); if (!func->isUnaryOperator() && shouldDereferenceArgumentPointer(func->arguments().first())) { secondArg.prepend('('); secondArg.append(')'); From a24e6bcd2251b6cbd78ec4e69a2b6b591738e697 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Wed, 29 Dec 2010 18:26:44 -0200 Subject: [PATCH 201/564] Add support for operator overload injection. Reviewer: Marcelo Lira Lauro Moura --- generator/cppgenerator.cpp | 40 +++++++++++-------- generator/shibokengenerator.cpp | 5 +++ .../samplebinding/objecttypeoperators_test.py | 3 ++ tests/samplebinding/typesystem_sample.xml | 8 +++- 4 files changed, 38 insertions(+), 18 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 5980fdad..41267eff 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2791,10 +2791,10 @@ void CppGenerator::writeRichCompareFunction(QTextStream& s, const AbstractMetaCl { QString baseName = cpythonBaseName(metaClass); s << "static PyObject* "; - s << baseName << "_richcompare(PyObject* self, PyObject* other, int op)" << endl; + s << baseName << "_richcompare(PyObject* self, PyObject* arg, int op)" << endl; s << '{' << endl; QList cmpOverloads = filterGroupedOperatorFunctions(metaClass, AbstractMetaClass::ComparisonOp); - s << INDENT << "PyObject* result = 0;" << endl; + s << INDENT << "PyObject* " PYTHON_RETURN_VAR " = 0;" << endl; s << INDENT << metaClass->qualifiedCppName() << "& " CPP_SELF_VAR " = *" << cpythonWrapperCPtr(metaClass) << ';' << endl; s << endl; @@ -2838,7 +2838,7 @@ void CppGenerator::writeRichCompareFunction(QTextStream& s, const AbstractMetaCl s << INDENT; } - s << "if (" << cpythonIsConvertibleFunction(type, numberType) << "(other)) {" << endl; + s << "if (" << cpythonIsConvertibleFunction(type, numberType) << "(arg)) {" << endl; { Indentation indent(INDENT); s << INDENT << "// " << func->signature() << endl; @@ -2846,21 +2846,27 @@ void CppGenerator::writeRichCompareFunction(QTextStream& s, const AbstractMetaCl s << translateTypeForWrapperMethod(type, 0, ExcludeReference | ExcludeConst); if (type->isObject() || type->isQObject()) s << '&'; - s << " cppOther = "; - writeToCppConversion(s, type, 0, "other", ExcludeReference | ExcludeConst); + s << " cppArg0 = "; + writeToCppConversion(s, type, 0, "arg", ExcludeReference | ExcludeConst); s << ';' << endl; - s << INDENT << "result = "; - if (!func->type()) { - s << "Py_None;" << endl; - s << INDENT << "Py_INCREF(Py_None);" << endl; - s << INDENT << CPP_SELF_VAR " " << op << " cppOther; // this op return void" << endl; + // If the function is user added, use the inject code + if (func->isUserAdded()) { + CodeSnipList snips = func->injectedCodeSnips(); + writeCodeSnips(s, snips, CodeSnip::Any, TypeSystem::TargetLangCode, func, func->arguments().last()); } else { - QByteArray self(CPP_SELF_VAR); - if (func->isPointerOperator()) - self.prepend('&'); - writeToPythonConversion(s, func->type(), metaClass, self + ' ' + op + " cppOther"); - s << ';' << endl; + s << INDENT << PYTHON_RETURN_VAR " = "; + if (!func->type()) { + s << "Py_None;" << endl; + s << INDENT << "Py_INCREF(Py_None);" << endl; + s << INDENT << CPP_SELF_VAR " " << op << " cppArg0; // this op return void" << endl; + } else { + QByteArray self(CPP_SELF_VAR); + if (func->isPointerOperator()) + self.prepend('&'); + writeToPythonConversion(s, func->type(), metaClass, self + ' ' + op + " cppArg0"); + s << ';' << endl; + } } } s << INDENT << '}'; @@ -2879,10 +2885,10 @@ void CppGenerator::writeRichCompareFunction(QTextStream& s, const AbstractMetaCl } s << INDENT << '}' << endl << endl; - s << INDENT << "if (result && !PyErr_Occurred())" << endl; + s << INDENT << "if (" PYTHON_RETURN_VAR " && !PyErr_Occurred())" << endl; { Indentation indent(INDENT); - s << INDENT << "return result;" << endl; + s << INDENT << "return " PYTHON_RETURN_VAR ";" << endl; } s << INDENT << baseName << "_RichComparison_TypeError:" << endl; s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \"operator not implemented.\");" << endl; diff --git a/generator/shibokengenerator.cpp b/generator/shibokengenerator.cpp index 2647e634..ebf63ab8 100644 --- a/generator/shibokengenerator.cpp +++ b/generator/shibokengenerator.cpp @@ -1218,6 +1218,11 @@ void ShibokenGenerator::writeCodeSnips(QTextStream& s, } else { cppSelf = "cppSelf"; } + + // on comparison operator cppSelf is always a reference. + if (func->isComparisonOperator()) + replacement = "%1."; + code.replace("%CPPSELF.", replacement.arg(cppSelf)); code.replace("%CPPSELF", cppSelf); diff --git a/tests/samplebinding/objecttypeoperators_test.py b/tests/samplebinding/objecttypeoperators_test.py index 148bc359..71e5a5d4 100644 --- a/tests/samplebinding/objecttypeoperators_test.py +++ b/tests/samplebinding/objecttypeoperators_test.py @@ -47,6 +47,9 @@ def testPointerOpeators(self): self.assertEqual("a", a) self.assertEqual(a, "a") + def testOperatorInjection(self): + a = ObjectTypeOperators("a") + self.assertNotEqual(a, "b") if __name__ == '__main__': unittest.main() diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 576c5465..5a518c34 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -1274,7 +1274,13 @@ - + + + + %PYARG_0 = %CONVERTTOPYTHON[bool](%CPPSELF.key() != %1); + + + From 7563560d32c91d0cf58567358a0f0f85c590056f Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Mon, 3 Jan 2011 11:10:32 -0300 Subject: [PATCH 202/564] Added a Linux man page for Shiboken. The man page was copied from the 'ubuntu' directory on the old 'packaging' repository. --- doc/CMakeLists.txt | 7 ++++- doc/shiboken.1 | 73 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 doc/shiboken.1 diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index d78844dc..57c8fa75 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -7,4 +7,9 @@ if (SPHINX) add_custom_target(doc ${SPHINX} -b html -c . ${CMAKE_CURRENT_SOURCE_DIR} html ) else() message("-- sphinx-build - not found! doc target disabled") -endif() \ No newline at end of file +endif() + +if (NOT win32) + file(GLOB manpages "${CMAKE_CURRENT_SOURCE_DIR}/*.1") + install(FILES ${manpages} DESTINATION share/man/man1) +endif() diff --git a/doc/shiboken.1 b/doc/shiboken.1 new file mode 100644 index 00000000..8aa25a7d --- /dev/null +++ b/doc/shiboken.1 @@ -0,0 +1,73 @@ +.TH SHIBOKEN "1" "March 2010" "shiboken v0.2.0" "User Commands" +.SH NAME +shiboken \- CPython bindings generator for C++ libraries +.SH DESCRIPTION +.SS "Usage:" +.IP +shiboken [options] header\-file typesystem\-file +.SS "General options:" +.TP +\fB\-\-debug\-level\fR=\fI[sparse\fR|medium|full] +Set the debug level +.TP +\fB\-\-documentation\-only\fR +Do not generates any code, just the documentation +.TP +\fB\-\-generatorSet\fR +generatorSet to be used. e.g. qtdoc +.TP +\fB\-\-help\fR +Display this help and exit +.TP +\fB\-\-include\-paths=\fR[::...] +Include paths used by the C++ parser +.TP +\fB\-\-license\-file\fR=\fI[licensefile]\fR +File used for copyright headers of generated files +.TP +\fB\-\-no\-suppress\-warnings\fR +Show all warnings +.TP +\fB\-\-output\-directory\fR=\fI[dir]\fR +The directory where the generated files will be written +.TP +\fB\-\-silent\fR +Avoid printing any message +.TP +\fB\-\-typesystem\-paths=\fR[::...] +Paths used when searching for typesystems +.TP +\fB\-\-version\fR +Output version information and exit +.SS "Shiboken options:" +.TP +\fB\-\-disable\-verbose\-error\-messages\fR +Disable verbose error messages. Turn the python code hard to debug but safe few kB on the generated bindings. +.TP +\fB\-\-enable\-parent\-ctor\-heuristic\fR +Enable heuristics to detect parent relationship on constructors. +.TP +\fB\-\-enable\-pyside\-extensions\fR +Enable PySide extensions, such as support for signal/slots, use this if you are creating a binding for a Qt\-based library. +.TP +\fB\-\-enable\-return\-value\-heuristic\fR +Enable heuristics to detect parent relationship on return values (USE WITH CAUTION!) +.SS "Shiboken options:" +.TP +\fB\-\-disable\-verbose\-error\-messages\fR +Disable verbose error messages. Turn the python code hard to debug but safe few kB on the generated bindings. +.TP +\fB\-\-enable\-parent\-ctor\-heuristic\fR +Enable heuristics to detect parent relationship on constructors. +.TP +\fB\-\-enable\-pyside\-extensions\fR +Enable PySide extensions, such as support for signal/slots, use this if you are creating a binding for a Qt\-based library. +.TP +\fB\-\-enable\-return\-value\-heuristic\fR +Enable heuristics to detect parent relationship on return values (USE WITH CAUTION!) +.SH COPYRIGHT +Copyright \(co 2009\-2010 Nokia Corporation and/or its subsidiary(\fB\-ies\fR) +.SH AUTHOR +.PP +This manpage was written for Debian, starting with a help2man output, by +Didier Raboud , on the 26. March 2010. From 3d2aef81fb97baefdc4b3a35a86076a8ed377100 Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Mon, 3 Jan 2011 15:34:35 -0300 Subject: [PATCH 203/564] A convertible check must be done on named arguments as it is done on regular arguments. --- generator/cppgenerator.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 41267eff..1c9c90fa 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -1818,11 +1818,18 @@ void CppGenerator::writeNamedArgumentResolution(QTextStream& s, const AbstractMe Indentation indent(INDENT); s << INDENT << "errorArgName = \"" << arg->name() << "\";" << endl; } - s << INDENT << "else" << endl; + s << INDENT << "else if ("; + writeTypeCheck(s, arg->type(), "value", isNumber(arg->type()->typeEntry())); + s << ')' << endl; { Indentation indent(INDENT); s << INDENT << pyArgName << " = value;" << endl; } + s << "else" << endl; + { + Indentation indent(INDENT); + s << INDENT << "goto " << cpythonFunctionName(func) << "_TypeError;" << endl; + } } s << INDENT << '}' << endl; s << INDENT; From 7ed5767ccfe005aaddfc2e5032dac2966154d87c Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Mon, 3 Jan 2011 15:33:07 -0300 Subject: [PATCH 204/564] Added test case for Bug #572. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug #572: Giving unicode value as 'body' argument to WebView's load method crashes python. Reviewed by Hugo Parente Reviewed by Renato Araújo --- tests/libsample/echo.h | 2 ++ tests/samplebinding/namedarg_test.py | 47 ++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 tests/samplebinding/namedarg_test.py diff --git a/tests/libsample/echo.h b/tests/libsample/echo.h index 40aed304..cc35ccd1 100644 --- a/tests/libsample/echo.h +++ b/tests/libsample/echo.h @@ -24,6 +24,7 @@ #define ECHO_H #include "libsamplemacros.h" +#include "str.h" class ObjectType; @@ -34,6 +35,7 @@ class Echo ~Echo(){} void doNothingWithConstBool(const bool hi) {} + void methodWithNamedArg(const Str& string = Str("")) {} // These method are here just for compilation test purposes Echo& operator<<(unsigned int item) { return *this; } diff --git a/tests/samplebinding/namedarg_test.py b/tests/samplebinding/namedarg_test.py new file mode 100644 index 00000000..f510b372 --- /dev/null +++ b/tests/samplebinding/namedarg_test.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# +# This file is part of the Shiboken Python Bindings Generator project. +# +# Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +# +# Contact: PySide team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# version 2.1 as published by the Free Software Foundation. Please +# review the following information to ensure the GNU Lesser General +# Public License version 2.1 requirements will be met: +# http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +# # +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +'''Bug #572: Giving unicode value as 'body' argument to WebView's load method crashes python.''' + +import unittest + +from sample import Echo + +class TestNamedArg(unittest.TestCase): + + def testRegularCall(self): + echo = Echo() + self.assertRaises(TypeError, echo.methodWithNamedArg, unicode('foo')) + + def testNamedArgumentCall(self): + echo = Echo() + self.assertRaises(TypeError, echo.methodWithNamedArg, string=unicode('foo')) + + +if __name__ == '__main__': + unittest.main() + From 786da143a916a81d11ba7bc4f14af71f6893584c Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 4 Jan 2011 18:48:25 -0200 Subject: [PATCH 205/564] Release the gil for every C++ function call, ignoring allow-thread attribute on typesystem. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewer: Marcelo Lira Renato Araújo --- generator/cppgenerator.cpp | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 1c9c90fa..9d8fb79f 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -1710,8 +1710,6 @@ void CppGenerator::writeFunctionCalls(QTextStream& s, const OverloadData& overlo s << INDENT << "{" << endl; { Indentation indent(INDENT); - if (overloadData.hasAllowThread()) - s << INDENT << "Shiboken::ThreadStateSaver " THREAD_STATE_SAVER_VAR ";" << endl; s << INDENT << (overloads.count() > 1 ? "switch (overloadId) " : "") << '{' << endl; { @@ -1905,9 +1903,6 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f // Used to provide contextual information to custom code writer function. const AbstractMetaArgument* lastArg = 0; - if (func->allowThread()) - s << INDENT << THREAD_STATE_SAVER_VAR ".save();" << endl; - CodeSnipList snips; if (func->hasInjectedCode()) { snips = func->injectedCodeSnips(); @@ -1934,9 +1929,6 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f if (convRules.size()) writeCodeSnips(s, convRules, CodeSnip::Beginning, TypeSystem::TargetLangCode, func); - // Code to restore the threadSaver has been written? - bool threadRestored = false; - if (!func->isUserAdded()) { bool badModifications = false; QStringList userArgs; @@ -2108,7 +2100,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f } if (!injectedCodeCallsCppFunction(func)) { - s << INDENT; + s << INDENT << "PyThreadState* _save = PyEval_SaveThread(); // Py_BEGIN_ALLOW_THREADS" << endl << INDENT; if (isCtor) { s << "cptr = "; } else if (func->type() && !func->isInplaceOperator()) { @@ -2129,11 +2121,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f s << " " CPP_RETURN_VAR " = "; } s << methodCall << ';' << endl; - - if (func->allowThread()) { - s << INDENT << THREAD_STATE_SAVER_VAR ".restore();" << endl; - threadRestored = true; - } + s << INDENT << "PyEval_RestoreThread(_save); // Py_END_ALLOW_THREADS" << endl; if (!isCtor && !func->isInplaceOperator() && func->type()) { s << INDENT << PYTHON_RETURN_VAR " = "; @@ -2143,9 +2131,6 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f } } - if (!threadRestored && func->allowThread()) - s << INDENT << THREAD_STATE_SAVER_VAR ".restore();" << endl; - if (func->hasInjectedCode() && !func->isConstructor()) { s << endl; writeCodeSnips(s, snips, CodeSnip::End, TypeSystem::TargetLangCode, func, lastArg); From 20f57828674fabc0ef1b5f0fbcea7c8732477979 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Wed, 5 Jan 2011 19:22:21 -0300 Subject: [PATCH 206/564] Use sleep function to give time to process breath. Fixes bug #580 Reviewer: Lauro Moura Hugo Parente Lima --- tests/libsample/bucket.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/libsample/bucket.cpp b/tests/libsample/bucket.cpp index b69ac7ec..b31ae1b4 100644 --- a/tests/libsample/bucket.cpp +++ b/tests/libsample/bucket.cpp @@ -23,6 +23,15 @@ #include "bucket.h" #include +#ifdef _WIN32 // _WIN32 is defined by all Windows 32 and 64 bit compilers, but not by others. +#include +#define SLEEP(x) Sleep(x) +#else +#include +#define SLEEP(x) usleep(x) +#endif + + using namespace std; Bucket::Bucket() : m_locked(false) @@ -54,7 +63,7 @@ bool Bucket::empty() void Bucket::lock() { m_locked = true; - while (m_locked); + while (m_locked) { SLEEP(300); } } void Bucket::unlock() From 635ae97b304dae295bf15d666c06c6e67660629b Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Fri, 7 Jan 2011 17:39:18 -0200 Subject: [PATCH 207/564] Fix bug#530 - "Importing division from future breaks QPoint division" Reviewer: Marcelo Lira Lauro Moura --- generator/cppgenerator.cpp | 2 +- tests/libsample/point.cpp | 6 ++++++ tests/libsample/point.h | 1 + tests/samplebinding/newdivision_test.py | 14 ++++++++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 tests/samplebinding/newdivision_test.py diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 9d8fb79f..95680b87 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2657,7 +2657,7 @@ void CppGenerator::writeTypeAsNumberDefinition(QTextStream& s, const AbstractMet s << INDENT << "/*nb_inplace_xor*/ (binaryfunc)" << nb["__ixor__"] << ',' << endl; s << INDENT << "/*nb_inplace_or*/ (binaryfunc)" << nb["__ior__"] << ',' << endl; s << INDENT << "/*nb_floor_divide*/ 0," << endl; - s << INDENT << "/*nb_true_divide*/ 0," << endl; + s << INDENT << "/*nb_true_divide*/ (binaryfunc)" << nb["__div__"] << ',' << endl; s << INDENT << "/*nb_inplace_floor_divide*/ 0," << endl; s << INDENT << "/*nb_inplace_true_divide*/ 0," << endl; s << INDENT << "/*nb_index*/ 0" << endl; diff --git a/tests/libsample/point.cpp b/tests/libsample/point.cpp index b8d310cf..484e7c11 100644 --- a/tests/libsample/point.cpp +++ b/tests/libsample/point.cpp @@ -118,6 +118,12 @@ operator!(const Point& pt) return (pt.m_x == 0.0 && pt.m_y == 0.0); } +Point +Point::operator/(int operand) +{ + return Point(m_x/operand, m_y/operand); +} + Complex transmutePointIntoComplex(const Point& point) { diff --git a/tests/libsample/point.h b/tests/libsample/point.h index 5c1e19a2..cc7a1bc5 100644 --- a/tests/libsample/point.h +++ b/tests/libsample/point.h @@ -54,6 +54,7 @@ class LIBSAMPLE_API Point Point operator+(const Point& other); Point operator-(const Point& other); + Point operator/(int operand); friend LIBSAMPLE_API Point operator*(const Point& pt, double mult); friend LIBSAMPLE_API Point operator*(const Point& pt, int mult); diff --git a/tests/samplebinding/newdivision_test.py b/tests/samplebinding/newdivision_test.py new file mode 100644 index 00000000..fbaeeab1 --- /dev/null +++ b/tests/samplebinding/newdivision_test.py @@ -0,0 +1,14 @@ +from __future__ import division +from sample import * +import unittest + +class TestNewDivision(unittest.TestCase): + + def testIt(self): + p = Point(4, 4) + p2 = p/2 + self.assertEqual(p2, Point(2, 2)) + +if __name__ == "__main__": + unittest.main() + From a0186b6c830f17ccbbf97cc234c9d903e16cc456 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Fri, 7 Jan 2011 15:54:12 -0300 Subject: [PATCH 208/564] Initialize ShibokenObject private data. This avoid errors during the functions call which uses the private data. Fixes bug #589 Reviewer: Marcelo Lira Hugo Parente --- libshiboken/basewrapper.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 8c0c2886..1f0327b7 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -333,6 +333,9 @@ void init() initTypeResolver(); PyEval_InitThreads(); + //Init private data + Shiboken::ObjectType::initPrivateData(&SbkObject_Type); + if (PyType_Ready(&SbkEnumType_Type) < 0) Py_FatalError("[libshiboken] Failed to initialise Shiboken.SbkEnumType metatype."); From 4234c5b8fa4ea2b7f5d3872bf87c92786b913abc Mon Sep 17 00:00:00 2001 From: Lauro Neto Date: Mon, 10 Jan 2011 09:22:50 -0300 Subject: [PATCH 209/564] Add test for invalid type returning from virtuals Returning an integer where the binding expects a pointer shouldn't segfault. --- .../invalid_virtual_return_test.py | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 tests/samplebinding/invalid_virtual_return_test.py diff --git a/tests/samplebinding/invalid_virtual_return_test.py b/tests/samplebinding/invalid_virtual_return_test.py new file mode 100644 index 00000000..164271e8 --- /dev/null +++ b/tests/samplebinding/invalid_virtual_return_test.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# This file is part of the Shiboken Python Bindings Generator project. +# +# Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +# +# Contact: PySide team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# version 2.1 as published by the Free Software Foundation. Please +# review the following information to ensure the GNU Lesser General +# Public License version 2.1 requirements will be met: +# http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +# # +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +'''Test case for returning invalid types in a virtual function''' + +import unittest +from sample import ObjectModel, ObjectType, ObjectView + + +class MyObject(ObjectType): + pass + + +class ListModelWrong(ObjectModel): + + def __init__(self, parent=None): + ObjectModel.__init__(self, parent) + self.obj = 0 + + def data(self): + # Shouldn't segfault. Must set TypeError + return self.obj + + +class ModelWrongReturnTest(unittest.TestCase): + + def testWrongTypeReturn(self): + model = ListModelWrong() + view = ObjectView(model) + self.assertRaises(TypeError, view.getRawModelData) # calls model.data() + + +if __name__ == '__main__': + unittest.main() From 5fccb1dafa71929b5a7968d5a3a99f5b442bc2e2 Mon Sep 17 00:00:00 2001 From: Lauro Neto Date: Mon, 10 Jan 2011 09:36:34 -0300 Subject: [PATCH 210/564] Fix SbkType name when setting exception in virtual Was generating SbkType with '*' in NAME, leading to segfaults. Reviewer: Marcelo Lira Reviewer: Luciano Wolf --- generator/cppgenerator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 95680b87..92dbf1f7 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -730,7 +730,7 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu if (func->type()->typeEntry()->isContainer()) { desiredType = '"' + reinterpret_cast(func->type()->typeEntry())->typeName() + '"'; } else { - QString typeName = func->type()->cppSignature(); + QString typeName = func->type()->typeEntry()->qualifiedCppName(); #ifdef AVOID_PROTECTED_HACK const AbstractMetaEnum* metaEnum = findAbstractMetaEnum(func->type()); if (metaEnum && metaEnum->isProtected()) From d9902755a46c299cd50550ae1c7932d1ac4d8f70 Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Tue, 11 Jan 2011 17:31:34 -0300 Subject: [PATCH 211/564] The overload decisor must put enums before types implicitly convertible from integers. Otherwise the enum value will be an acceptable argument for a class that expects an integer (signed or unsigned) to be implicitly built, and the enum argument will never be called. --- generator/overloaddata.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/generator/overloaddata.cpp b/generator/overloaddata.cpp index 29a1615f..926f5d98 100644 --- a/generator/overloaddata.cpp +++ b/generator/overloaddata.cpp @@ -225,11 +225,14 @@ void OverloadData::sortNextOverloads() for (int i = 0; i < numPrimitives; ++i) hasPrimitive[i] = sortData.map.contains(primitiveTypes[i]); + QStringList classesWithIntegerImplicitConversion; + foreach(OverloadData* ov, m_nextOverloadData) { const AbstractMetaType* targetType = ov->argType(); const TypeEntry* targetTypeEntry = getAliasedTypeEntry(targetType->typeEntry()); QString targetTypeEntryName = getTypeName(targetType); + // Process implicit conversions foreach(AbstractMetaFunction* function, m_generator->implicitConversions(targetType)) { QString convertibleType; if (function->isConversionOperator()) @@ -237,6 +240,9 @@ void OverloadData::sortNextOverloads() else convertibleType = getTypeName(function->arguments().first()->type()); + if (convertibleType == "int" || convertibleType == "unsigned int") + classesWithIntegerImplicitConversion << targetTypeEntryName; + if (!sortData.map.contains(convertibleType)) continue; @@ -249,6 +255,8 @@ void OverloadData::sortNextOverloads() graph.addEdge(convertibleTypeId, targetTypeId); } + + // Process template instantiations foreach (const AbstractMetaType* instantiation, targetType->instantiations()) { if (sortData.map.contains(getTypeName(instantiation))) { int target = sortData.map[targetTypeEntryName]; @@ -286,6 +294,7 @@ void OverloadData::sortNextOverloads() } if (targetTypeEntry->isEnum()) { + // Enum values must precede primitive types. for (int i = 0; i < numPrimitives; ++i) { if (hasPrimitive[i]) graph.addEdge(sortData.map[targetTypeEntryName], sortData.map[primitiveTypes[i]]); @@ -293,6 +302,20 @@ void OverloadData::sortNextOverloads() } } + foreach(OverloadData* ov, m_nextOverloadData) { + const AbstractMetaType* targetType = ov->argType(); + if (!targetType->isEnum()) + continue; + + const TypeEntry* targetTypeEntry = getAliasedTypeEntry(targetType->typeEntry()); + QString targetTypeEntryName = getTypeName(targetType); + + // Enum values must precede types implicitly convertible from "int" or "unsigned int". + foreach (const QString& implicitFromInt, classesWithIntegerImplicitConversion) + graph.addEdge(sortData.map[targetTypeEntryName], sortData.map[implicitFromInt]); + } + + // Special case for double(int i) (not tracked by m_generator->implicitConversions foreach (const QString& signedIntegerName, signedIntegerPrimitives) { if (sortData.map.contains(signedIntegerName)) { From 498ba2f39e64129d6911cedfd1334032350543eb Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Tue, 11 Jan 2011 17:34:28 -0300 Subject: [PATCH 212/564] Added test to assert the precedence of enum arguments over int implicit conversions. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This test is inspired by bug #511 [1], and it checks the precedence of an enum argument over a class that can be implicitly built from an integer. [1] http://bugs.openbossa.org/show_bug.cgi?id=511 Reviewed by Luciano Wolf Reviewed by Renato Araújo --- tests/libsample/pen.h | 52 ++++++++++++++++++++ tests/samplebinding/CMakeLists.txt | 2 + tests/samplebinding/global.h | 1 + tests/samplebinding/pen_test.py | 59 +++++++++++++++++++++++ tests/samplebinding/typesystem_sample.xml | 5 ++ 5 files changed, 119 insertions(+) create mode 100644 tests/libsample/pen.h create mode 100644 tests/samplebinding/pen_test.py diff --git a/tests/libsample/pen.h b/tests/libsample/pen.h new file mode 100644 index 00000000..9c97c2e3 --- /dev/null +++ b/tests/libsample/pen.h @@ -0,0 +1,52 @@ +/* + * This file is part of the Shiboken Python Binding Generator project. + * + * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + * + * Contact: PySide team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef PEN_H +#define PEN_H + +#include "libsamplemacros.h" +#include "samplenamespace.h" + +class LIBSAMPLE_API Color +{ +public: + Color() {} + Color(SampleNamespace::InValue arg) {} + Color(unsigned int arg) {} +}; + +class LIBSAMPLE_API Pen +{ +public: + enum { EmptyCtor, EnumCtor, ColorCtor, CopyCtor }; + + Pen() : m_ctor(EmptyCtor) {} + Pen(SampleNamespace::Option option) : m_ctor(EnumCtor) {} + Pen(const Color& color) : m_ctor(ColorCtor) {} + Pen(const Pen& pen) : m_ctor(CopyCtor) {} + + int ctorType() { return m_ctor; } +private: + int m_ctor; +}; + +#endif diff --git a/tests/samplebinding/CMakeLists.txt b/tests/samplebinding/CMakeLists.txt index 1fa95501..c81209c2 100644 --- a/tests/samplebinding/CMakeLists.txt +++ b/tests/samplebinding/CMakeLists.txt @@ -16,6 +16,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/base6_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/blackbox_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/bucket_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/collector_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/color_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/ctorconvrule_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/sbkdate_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/derived_wrapper.cpp @@ -51,6 +52,7 @@ ${CMAKE_CURRENT_BINARY_DIR}/sample/objtypereference_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/oddbooluser_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/overload_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/pairuser_wrapper.cpp +${CMAKE_CURRENT_BINARY_DIR}/sample/pen_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/point_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/pointf_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/sample/pointerholder_wrapper.cpp diff --git a/tests/samplebinding/global.h b/tests/samplebinding/global.h index 181ed29f..18ad5646 100644 --- a/tests/samplebinding/global.h +++ b/tests/samplebinding/global.h @@ -29,6 +29,7 @@ #include "oddbool.h" #include "overload.h" #include "pairuser.h" +#include "pen.h" #include "point.h" #include "pointf.h" #include "pointerholder.h" diff --git a/tests/samplebinding/pen_test.py b/tests/samplebinding/pen_test.py new file mode 100644 index 00000000..52e79e2d --- /dev/null +++ b/tests/samplebinding/pen_test.py @@ -0,0 +1,59 @@ +#!/usr/bin/env python + +# -*- coding: utf-8 -*- +# +# This file is part of the Shiboken Python Bindings Generator project. +# +# Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +# +# Contact: PySide team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public License +# version 2.1 as published by the Free Software Foundation. Please +# review the following information to ensure the GNU Lesser General +# Public License version 2.1 requirements will be met: +# http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +# # +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +'''Test cases for with const char* as argument''' + +import unittest + +from sample import Color, Pen, SampleNamespace + +class TestPen(unittest.TestCase): + '''Simple test case for Pen.''' + + def testPenWithEmptyConstructor(self): + pen = Pen() + self.assertEqual(pen.ctorType(), Pen.EmptyCtor) + + def testPenWithEnumConstructor(self): + pen = Pen(SampleNamespace.RandomNumber) + self.assertEqual(pen.ctorType(), Pen.EnumCtor) + + def testPenWithColorConstructor(self): + pen = Pen(Color()) + self.assertEqual(pen.ctorType(), Pen.ColorCtor) + + def testPenWithCopyConstructor(self): + pen = Pen(Pen()) + self.assertEqual(pen.ctorType(), Pen.CopyCtor) + + def testPenWithIntConvertedToColor(self): + pen = Pen(1) + self.assertEqual(pen.ctorType(), Pen.ColorCtor) + +if __name__ == '__main__': + unittest.main() + diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index 5a518c34..2667c16d 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -1238,6 +1238,11 @@ + + + + + From 297151081ffae13c8dbb66ffde61f2c15eaae2a3 Mon Sep 17 00:00:00 2001 From: Lauro Neto Date: Tue, 11 Jan 2011 17:07:26 -0300 Subject: [PATCH 213/564] Append python name to libshiboken output file libshiboken is strongly tied to the python it was compiled against. This commit adds the python name to the output file to make this connection explicit. The generator plugin, binary and includes are untouched as they don't depend on python. Also, Instead of installing the cmake info in a single file, ShibokenConfig.cmake will load the correct file (ShibokenConfig-.cmake) based on the value of PYTHON_BASENAME when cmake is called. The last shiboken installed will be the default as each install will overwrite ShibokenConfig.cmake. To select an specific python, call cmake with -DPYTHON_BASENAME=python2.6, for python2.6 release. Reviewer: Marcelo Lira Lauro Moura --- CMakeLists.txt | 10 ++++++++++ data/CMakeLists.txt | 4 ++++ data/ShibokenConfig-spec.cmake.in | 29 +++++++++++++++++++++++++++++ data/ShibokenConfig.cmake.in | 31 ++++--------------------------- libshiboken/CMakeLists.txt | 2 +- 5 files changed, 48 insertions(+), 28 deletions(-) create mode 100644 data/ShibokenConfig-spec.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index d0891ce9..52aea434 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,6 +70,16 @@ execute_process( OUTPUT_VARIABLE PY_DEBUG OUTPUT_STRIP_TRAILING_WHITESPACE) + +execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c "import sys; \\ + from distutils import sysconfig; \\ + vr = sys.version_info; \\ + suffix = '-dbg' if bool(sysconfig.get_config_var('Py_DEBUG')) else ''; \\ + print 'python%d.%d%s' % (vr[0], vr[1], suffix)" + OUTPUT_VARIABLE PYTHON_BASENAME + OUTPUT_STRIP_TRAILING_WHITESPACE) + set(SHIBOKEN_BUILD_TYPE "Release") if(CMAKE_BUILD_TYPE STREQUAL "Debug") if(NOT PYTHON_DEBUG_LIBRARIES) diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt index 9ad9381d..66838599 100644 --- a/data/CMakeLists.txt +++ b/data/CMakeLists.txt @@ -6,6 +6,8 @@ endif() configure_file("${CMAKE_CURRENT_SOURCE_DIR}/ShibokenConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/ShibokenConfig.cmake" @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/ShibokenConfig-spec.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/ShibokenConfig-${PYTHON_BASENAME}.cmake" @ONLY) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/ShibokenConfigVersion.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/ShibokenConfigVersion.cmake" @ONLY) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/shiboken.pc.in" @@ -13,6 +15,8 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/shiboken.pc.in" install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ShibokenConfig.cmake" DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken-${shiboken_VERSION}") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ShibokenConfig-${PYTHON_BASENAME}.cmake" + DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken-${shiboken_VERSION}") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ShibokenConfigVersion.cmake" DESTINATION "${LIB_INSTALL_DIR}/cmake/Shiboken-${shiboken_VERSION}") install(FILES "${CMAKE_CURRENT_BINARY_DIR}/shiboken${shiboken_SUFFIX}.pc" diff --git a/data/ShibokenConfig-spec.cmake.in b/data/ShibokenConfig-spec.cmake.in new file mode 100644 index 00000000..36f0e733 --- /dev/null +++ b/data/ShibokenConfig-spec.cmake.in @@ -0,0 +1,29 @@ +# SHIBOKEN_INCLUDE_DIR - Directories to include to use SHIBOKEN +# SHIBOKEN_LIBRARIES - Files to link against to use SHIBOKEN +# SHIBOKEN_BUILD_TYPE - Tells if Shiboken was compiled in Release or Debug mode. +# SHIBOKEN_PYTHON_INTERPRETER - Python interpreter (regular or debug) to be used with the bindings. +# SHIBOKEN_PYTHON_LIBRARIES - Python libraries (regular or debug) Shiboken is linked against. + +SET(SHIBOKEN_INCLUDE_DIR "@CMAKE_INSTALL_PREFIX@/include/shiboken@shiboken_SUFFIX@") +if(MSVC) + SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@-@PYTHON_BASENAME@@LIBRARY_OUTPUT_SUFFIX@.lib") +elseif(WIN32) + SET(SHIBOKEN_LIBRARY "@CMAKE_INSTALL_PREFIX@/bin/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@-@PYTHON_BASENAME@@LIBRARY_OUTPUT_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") +else() + SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@-@PYTHON_BASENAME@@LIBRARY_OUTPUT_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") +endif() +SET(SHIBOKEN_PYTHON_INCLUDE_DIR "@SBK_PYTHON_INCLUDE_DIR@") +SET(SHIBOKEN_PYTHON_INCLUDE_DIR "@SBK_PYTHON_INCLUDE_DIR@") +SET(SHIBOKEN_PYTHON_INTERPRETER "@PYTHON_EXECUTABLE@") +SET(SHIBOKEN_PYTHON_LIBRARIES "@SBK_PYTHON_LIBRARIES@") +SET(SHIBOKEN_PYTHON_BASENAME "@PYTHON_BASENAME@") +message(STATUS "libshiboken built for @SHIBOKEN_BUILD_TYPE@") +@SBK_ADD_PY_DEBUG_DEFINITION@ + +# We don't use just "if (@AVOID_PROTECTED_HACK@)" to avoid require all users to turn on the cmake policy CMP0012 +# for more info type: cmake --help-policy CMP0012 +set(SHIBOKEN_AVOID_PROTECTED_HACK @AVOID_PROTECTED_HACK@) +if (SHIBOKEN_AVOID_PROTECTED_HACK) + add_definitions(-DAVOID_PROTECTED_HACK) + message(STATUS "Avoiding protected hack!") +endif() diff --git a/data/ShibokenConfig.cmake.in b/data/ShibokenConfig.cmake.in index c7abc831..92f5d02c 100644 --- a/data/ShibokenConfig.cmake.in +++ b/data/ShibokenConfig.cmake.in @@ -1,28 +1,5 @@ -# SHIBOKEN_INCLUDE_DIR - Directories to include to use SHIBOKEN -# SHIBOKEN_LIBRARIES - Files to link against to use SHIBOKEN -# SHIBOKEN_BUILD_TYPE - Tells if Shiboken was compiled in Release or Debug mode. -# SHIBOKEN_PYTHON_INTERPRETER - Python interpreter (regular or debug) to be used with the bindings. -# SHIBOKEN_PYTHON_LIBRARIES - Python libraries (regular or debug) Shiboken is linked against. - -SET(SHIBOKEN_INCLUDE_DIR "@CMAKE_INSTALL_PREFIX@/include/shiboken@shiboken_SUFFIX@") -if(MSVC) - SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@.lib") -elseif(WIN32) - SET(SHIBOKEN_LIBRARY "@CMAKE_INSTALL_PREFIX@/bin/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") -else() - SET(SHIBOKEN_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@shiboken@shiboken_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@") -endif() -SET(SHIBOKEN_PYTHON_INCLUDE_DIR "@SBK_PYTHON_INCLUDE_DIR@") -SET(SHIBOKEN_PYTHON_INTERPRETER "@PYTHON_EXECUTABLE@") -SET(SHIBOKEN_PYTHON_LIBRARIES "@SBK_PYTHON_LIBRARIES@") -SET(SHIBOKEN_BUILD_TYPE "@SHIBOKEN_BUILD_TYPE@") -message(STATUS "libshiboken built for @SHIBOKEN_BUILD_TYPE@") -@SBK_ADD_PY_DEBUG_DEFINITION@ - -# We don't use just "if (@AVOID_PROTECTED_HACK@)" to avoid require all users to turn on the cmake policy CMP0012 -# for more info type: cmake --help-policy CMP0012 -set(SHIBOKEN_AVOID_PROTECTED_HACK @AVOID_PROTECTED_HACK@) -if (SHIBOKEN_AVOID_PROTECTED_HACK) - add_definitions(-DAVOID_PROTECTED_HACK) - message(STATUS "Avoiding protected hack!") +if (NOT PYTHON_BASENAME) + message(STATUS "Using default python: @PYTHON_BASENAME@") + SET(PYTHON_BASENAME @PYTHON_BASENAME@) endif() +include(@LIB_INSTALL_DIR@/cmake/Shiboken-@shiboken_VERSION@/ShibokenConfig-${PYTHON_BASENAME}.cmake) diff --git a/libshiboken/CMakeLists.txt b/libshiboken/CMakeLists.txt index 36156065..d08c1f45 100644 --- a/libshiboken/CMakeLists.txt +++ b/libshiboken/CMakeLists.txt @@ -36,7 +36,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${SPARSEHASH_INCLUDE_PATH}) add_library(libshiboken SHARED ${libshiboken_SRC}) target_link_libraries(libshiboken ${SBK_PYTHON_LIBRARIES}) -set_target_properties(libshiboken PROPERTIES OUTPUT_NAME "shiboken${shiboken_SUFFIX}" +set_target_properties(libshiboken PROPERTIES OUTPUT_NAME "shiboken${shiboken_SUFFIX}-${PYTHON_BASENAME}" VERSION ${libshiboken_VERSION} SOVERSION ${libshiboken_SOVERSION} DEFINE_SYMBOL LIBSHIBOKEN_EXPORTS) From b719c4e8b9238ea8c4d1e022cf597e8cb628f5d7 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Wed, 12 Jan 2011 19:30:23 -0300 Subject: [PATCH 214/564] Optimized setParent function. Replaced use of find in the children list for check on the current child if his has a parent and if the parent is the same. Fixes bug #556 Reviewer: Marcelo Lira Hugo Parente --- libshiboken/basewrapper.cpp | 4 ++-- tests/samplebinding/ownership_reparenting_test.py | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 1f0327b7..71892e42 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -910,9 +910,9 @@ void setParent(PyObject* parent, PyObject* child) if (!parentIsNull) { if (!parent_->d->parentInfo) parent_->d->parentInfo = new ParentInfo; + // do not re-add a child - ChildrenList& children = parent_->d->parentInfo->children; - if (std::find(children.begin(), children.end(), child_) != children.end()) + if (child_->d->parentInfo && (child_->d->parentInfo->parent == parent_)) return; } diff --git a/tests/samplebinding/ownership_reparenting_test.py b/tests/samplebinding/ownership_reparenting_test.py index 3e68287b..395ce393 100644 --- a/tests/samplebinding/ownership_reparenting_test.py +++ b/tests/samplebinding/ownership_reparenting_test.py @@ -27,6 +27,7 @@ '''Tests for object reparenting.''' import unittest +import sys from sample import ObjectType @@ -52,6 +53,15 @@ def testReparentedObjectTypeIdentity(self): for child in new_parent.children(): self.assert_(child in object_list) + def testReparentWithTheSameParent(self): + '''Set the same parent twice to check if the ref continue the same''' + obj = ObjectType() + parent = ObjectType() + self.assertEqual(sys.getrefcount(obj), 2) + obj.setParent(parent) + self.assertEqual(sys.getrefcount(obj), 3) + obj.setParent(parent) + self.assertEqual(sys.getrefcount(obj), 3) def testReparentedExtObjectType(self): '''Reparent children from one extended parent to another.''' From 2094d56e312a9f35e606cac30aff4bdd0f2dd13d Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Wed, 12 Jan 2011 16:24:10 -0300 Subject: [PATCH 215/564] Updated Shiboken documentation with advice about duck punching and virtual methods. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed by Luciano Wolf Reviewed by Renato Araújo --- doc/_templates/index.html | 2 ++ doc/contents.rst | 1 + doc/wordsofadvice.rst | 71 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 doc/wordsofadvice.rst diff --git a/doc/_templates/index.html b/doc/_templates/index.html index 076f3bd3..129a398b 100644 --- a/doc/_templates/index.html +++ b/doc/_templates/index.html @@ -25,6 +25,8 @@

Documentation

support for python sequence protocol

+ diff --git a/doc/contents.rst b/doc/contents.rst index 6292e952..a9721693 100644 --- a/doc/contents.rst +++ b/doc/contents.rst @@ -10,3 +10,4 @@ Table of contents codeinjectionsemantics.rst sequenceprotocol.rst ownership.rst + wordsofadvice.rst diff --git a/doc/wordsofadvice.rst b/doc/wordsofadvice.rst new file mode 100644 index 00000000..d27cae00 --- /dev/null +++ b/doc/wordsofadvice.rst @@ -0,0 +1,71 @@ +.. _words-of-advice: + +*************** +Words of Advice +*************** + +When writing or using Python bindings there is some things you must keep in mind. + + +.. _duck-punching-and-virtual-methods: + +Duck punching and virtual methods +================================= + +The combination of duck punching, the practice of altering class characteristics +of already instantiated objects, and virtual methods of wrapped C++ classes, can +be tricky. That was an optimistic statement. + +Let's see duck punching in action for educational purposes. + + .. code-block:: python + + import types + import Binding + + obj = Binding.CppClass() + + # CppClass has a virtual method called 'virtualMethod', + # but we don't like it anymore. + def myVirtualMethod(self_obj, arg): + pass + + obj.virtualMethod = types.MethodType(myVirtualMethod, obj, Binding.CppClass) + + +If some C++ code happens to call `CppClass::virtualMethod(...)` on the C++ object +held by "obj" Python object, the new duck punched "virtualMethod" method will be +properly called. That happens because the underlying C++ object is in fact an instance +of a generated C++ class that inherits from `CppClass`, let's call it `CppClassWrapper`, +responsible for receiving the C++ virtual method calls and finding out the proper Python +override to which handle such a call. + +Now that you know this, consider the case when C++ has a factory method that gives you +new C++ objects originated somewhere in C++-land, in opposition to the ones generated in +Python-land by the usage of class constructors, like in the example above. + +Brief interruption to show what I was saying: + + .. code-block:: python + + import types + import Binding + + obj = Binding.createCppClass() + def myVirtualMethod(self_obj, arg): + pass + + # Punching a dead duck... + obj.virtualMethod = types.MethodType(myVirtualMethod, obj, Binding.CppClass) + + +The `Binding.createCppClass()` factory method is just an example, C++ created objects +can pop out for a number of other reasons. Objects created this way have a Python wrapper +holding them as usual, but the object held is not a `CppClassWrapper`, but a regular +`CppClass`. All virtual method calls originated in C++ will stay in C++ and never reach +a Python virtual method overridden via duck punching. + +Although duck punching is an interesting Python feature, it don't mix well with wrapped +C++ virtual methods, specially when you can't tell the origin of every single wrapped +C++ object. In summary: don't do it! + From 99760ad3ed66e619e04defcdfe05710899c7afc9 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Thu, 13 Jan 2011 15:04:03 -0300 Subject: [PATCH 216/564] Used c++ pointer during the c++ class attribute get function. Now all function get for class attribute return the internal memory of the c++ attribute. Reviewer: Hugo Parente Luciano Wolf --- generator/cppgenerator.cpp | 34 +++++++++++++++++++----- libshiboken/bindingmanager.cpp | 2 -- tests/samplebinding/class_fields_test.py | 9 ++++++- 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 92dbf1f7..28ab0b71 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2709,18 +2709,40 @@ void CppGenerator::writeGetterFunction(QTextStream& s, const AbstractMetaField* { s << "static PyObject* " << cpythonGetterFunctionName(metaField) << "(PyObject* self, void*)" << endl; s << '{' << endl; - s << INDENT << "return "; + s << INDENT << "PyObject* val = "; QString cppField; + AbstractMetaType *metaType = metaField->type(); + // Force use of pointer to return internal variable memory + bool useReference = (!metaType->isConstant() && + !metaType->isEnum() && + !metaType->isPrimitive() && + metaType->indirections() == 0); + #ifdef AVOID_PROTECTED_HACK if (metaField->isProtected()) - cppField = QString("((%1*)%2)->%3()").arg(wrapperName(metaField->enclosingClass())).arg(cpythonWrapperCPtr(metaField->enclosingClass(), "self")).arg(protectedFieldGetterName(metaField)); + cppField = QString("(%1(%2*)%3)->%4()") + .arg(useReference ? '&' : ' ') + .arg(wrapperName(metaField->enclosingClass())) + .arg(cpythonWrapperCPtr(metaField->enclosingClass(), "self")) + .arg(protectedFieldGetterName(metaField)); else #endif - cppField= QString("%1->%2").arg(cpythonWrapperCPtr(metaField->enclosingClass(), "self")).arg(metaField->name()); - writeToPythonConversion(s, metaField->type(), metaField->enclosingClass(), cppField); - s << ';' << endl; - s << '}' << endl; + cppField= QString("%1%2->%3") + .arg(useReference ? '&' : ' ') + .arg(cpythonWrapperCPtr(metaField->enclosingClass(), "self")) + .arg(metaField->name()); + + if (useReference) { + s << INDENT << "Shiboken::createWrapper(" << cppField << ");" << endl; + s << INDENT << "Shiboken::Object::releaseOwnership(val);" << endl; + } else { + writeToPythonConversion(s, metaField->type(), metaField->enclosingClass(), cppField); + s << ';' << endl; + } + + s << INDENT << "return val;" << endl + << endl << '}' << endl; } void CppGenerator::writeSetterFunction(QTextStream& s, const AbstractMetaField* metaField) diff --git a/libshiboken/bindingmanager.cpp b/libshiboken/bindingmanager.cpp index 3aa4c88e..ba9f77eb 100644 --- a/libshiboken/bindingmanager.cpp +++ b/libshiboken/bindingmanager.cpp @@ -128,8 +128,6 @@ void BindingManager::BindingManagerPrivate::assignWrapper(SbkObject* wrapper, co WrapperMap::iterator iter = wrapperMapper.find(cptr); if (iter == wrapperMapper.end()) wrapperMapper.insert(std::make_pair(cptr, wrapper)); - else - iter->second = wrapper; } BindingManager::BindingManager() diff --git a/tests/samplebinding/class_fields_test.py b/tests/samplebinding/class_fields_test.py index f0791e1d..c01a6bf0 100644 --- a/tests/samplebinding/class_fields_test.py +++ b/tests/samplebinding/class_fields_test.py @@ -64,7 +64,14 @@ def testAccessingValueTypeField(self): new_value = Point(-10, 537) d.valueTypeField = new_value self.assertEqual(d.valueTypeField, new_value) - self.assert_(not d.valueTypeField == old_value) + + #object modify + d.valueTypeField.setX(10) + d.valueTypeField.setY(20) + self.assertEqual(d.valueTypeField.x(), 10) + self.assertEqual(d.valueTypeField.y(), 20) + + # attribution with invalid type self.assertRaises(TypeError, lambda : setattr(d, 'valueTypeField', 123)) From cde05a92336a9f5fee1d8d1f591c89dd1ee70328 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Wed, 19 Jan 2011 09:38:17 -0300 Subject: [PATCH 217/564] Fix windows compilation. Reviewer: Hugo Parente Luciano Wolf --- generator/cppgenerator.cpp | 3 +-- generator/headergenerator.cpp | 24 +++++++++++++++++++----- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 28ab0b71..c249eb21 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -2721,8 +2721,7 @@ void CppGenerator::writeGetterFunction(QTextStream& s, const AbstractMetaField* #ifdef AVOID_PROTECTED_HACK if (metaField->isProtected()) - cppField = QString("(%1(%2*)%3)->%4()") - .arg(useReference ? '&' : ' ') + cppField = QString("((%1*)%2)->%3()") .arg(wrapperName(metaField->enclosingClass())) .arg(cpythonWrapperCPtr(metaField->enclosingClass(), "self")) .arg(protectedFieldGetterName(metaField)); diff --git a/generator/headergenerator.cpp b/generator/headergenerator.cpp index 9a28cdb9..bb8f341a 100644 --- a/generator/headergenerator.cpp +++ b/generator/headergenerator.cpp @@ -47,13 +47,27 @@ void HeaderGenerator::writeCopyCtor(QTextStream& s, const AbstractMetaClass* met void HeaderGenerator::writeProtectedFieldAccessors(QTextStream& s, const AbstractMetaField* field) const { - QString fieldType = field->type()->cppSignature(); + AbstractMetaType *metaType = field->type(); + QString fieldType = metaType->cppSignature(); QString fieldName = field->enclosingClass()->qualifiedCppName() + "::" + field->name(); - s << INDENT << "inline " << fieldType << ' ' << protectedFieldGetterName(field) << "()"; - s << " { return " << fieldName << "; }" << endl; - s << INDENT << "inline void " << protectedFieldSetterName(field) << '(' << fieldType << " value)"; - s << " { " << fieldName << " = value; }" << endl; + // Force use of pointer to return internal variable memory + bool useReference = (!metaType->isConstant() && + !metaType->isEnum() && + !metaType->isPrimitive() && + metaType->indirections() == 0); + + + // Get function + s << INDENT << "inline " << fieldType + << (useReference ? '*' : ' ') + << ' ' << protectedFieldGetterName(field) << "()" + << " { return " + << (useReference ? '&' : ' ') << "this->" << fieldName << "; }" << endl; + + // Set function + s << INDENT << "inline void " << protectedFieldSetterName(field) << '(' << fieldType << " value)" + << " { " << fieldName << " = value; }" << endl; } void HeaderGenerator::generateClass(QTextStream& s, const AbstractMetaClass* metaClass) From 3483a54e6b84210e101d905b55d00858070ab62d Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Tue, 18 Jan 2011 18:20:00 -0300 Subject: [PATCH 218/564] Added more test cases for protected attributes. The tests are meant to be useful when compiled without the protected hack or on the win32 platform. Reviewed by Hugo Parente Reviewed by Luciano Wolf --- tests/libsample/protected.h | 14 ++++++++- tests/samplebinding/protected_test.py | 44 +++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/tests/libsample/protected.h b/tests/libsample/protected.h index bf4dea04..645dd93e 100644 --- a/tests/libsample/protected.h +++ b/tests/libsample/protected.h @@ -24,6 +24,8 @@ #define PROTECTED_H #include "libsamplemacros.h" +#include "objecttype.h" +#include "point.h" #include class ProtectedNonPolymorphic @@ -117,9 +119,19 @@ class ProtectedEnumClass class ProtectedProperty { public: - ProtectedProperty() : protectedProperty(0) {} + ProtectedProperty() + : protectedProperty(0), + protectedEnumProperty(Event::NO_EVENT), + protectedValueTypeProperty(Point(0, 0)), + protectedValueTypePointerProperty(0), + protectedObjectTypeProperty(0) + {} protected: int protectedProperty; + Event::EventType protectedEnumProperty; + Point protectedValueTypeProperty; + Point* protectedValueTypePointerProperty; + ObjectType* protectedObjectTypeProperty; }; #endif // PROTECTED_H diff --git a/tests/samplebinding/protected_test.py b/tests/samplebinding/protected_test.py index e9d8b81e..8ebc99f1 100644 --- a/tests/samplebinding/protected_test.py +++ b/tests/samplebinding/protected_test.py @@ -27,14 +27,13 @@ '''Test cases for protected methods.''' import unittest -import sys from sample import cacheSize from sample import ProtectedNonPolymorphic, ProtectedVirtualDestructor from sample import ProtectedPolymorphic, ProtectedPolymorphicDaughter, ProtectedPolymorphicGrandDaughter from sample import ProtectedProperty, ProtectedEnumClass from sample import PrivateDtor -from sample import Point +from sample import Event, ObjectType, Point class ExtendedProtectedPolymorphic(ProtectedPolymorphic): def __init__(self, name): @@ -266,15 +265,48 @@ def testOverriddenProtectedMethodWithPublicEnumArgument(self): class ProtectedPropertyTest(unittest.TestCase): '''Test cases for a class with a protected property (or field in C++).''' + def setUp(self): + self.obj = ProtectedProperty() + def tearDown(self): + del self.obj self.assertEqual(cacheSize(), 0) def testProtectedProperty(self): - '''Writes and reads a protected property.''' - obj = ProtectedProperty() + '''Writes and reads a protected integer property.''' + self.obj.protectedProperty = 3 + self.assertEqual(self.obj.protectedProperty, 3) + + def testProtectedEnumProperty(self): + '''Writes and reads a protected enum property.''' + self.obj.protectedEnumProperty = Event.SOME_EVENT + self.assertEqual(self.obj.protectedEnumProperty, Event.SOME_EVENT) + + def testProtectedValueTypeProperty(self): + '''Writes and reads a protected value type property.''' + point = Point(12, 34) + self.obj.protectedValueTypeProperty = point + self.assertEqual(self.obj.protectedValueTypeProperty, point) + self.assertFalse(self.obj.protectedValueTypeProperty is point) + pointProperty = self.obj.protectedValueTypeProperty + self.assertFalse(self.obj.protectedValueTypeProperty is pointProperty) + + def testProtectedValueTypePointerProperty(self): + '''Writes and reads a protected value type pointer property.''' + pt1 = Point(12, 34) + pt2 = Point(12, 34) + self.obj.protectedValueTypePointerProperty = pt1 + self.assertEqual(self.obj.protectedValueTypePointerProperty, pt1) + self.assertEqual(self.obj.protectedValueTypePointerProperty, pt2) + self.assert_(self.obj.protectedValueTypePointerProperty is pt1) + self.assertFalse(self.obj.protectedValueTypePointerProperty is pt2) + + def testProtectedObjectTypeProperty(self): + '''Writes and reads a protected object type property.''' + obj = ObjectType() + self.obj.protectedObjectTypeProperty = obj + self.assertEqual(self.obj.protectedObjectTypeProperty, obj) - obj.protectedProperty = 3 - self.assertEqual(obj.protectedProperty, 3) class PrivateDtorProtectedMethodTest(unittest.TestCase): '''Test cases for classes with private destructors and protected methods.''' From 4721af29a2225389528ba5984c53ab551058e690 Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Tue, 18 Jan 2011 16:51:24 -0200 Subject: [PATCH 219/564] Add Shiboken::Object::isValid(SbkObject* pyObj, bool throwPyError = true) function to libshiboken. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function is needed to fix bug#552 when a libpyside code needs to check if a SbkObject is valid without set a Python error when it isn't. Reviewer: Marcelo Lira Renato Araújo --- libshiboken/basewrapper.cpp | 8 ++++++++ libshiboken/basewrapper.h | 9 ++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 71892e42..2d82510e 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -785,6 +785,14 @@ bool isValid(PyObject* pyObj) return false; } +bool isValid(SbkObject* pyObj, bool throwPyError) +{ + bool result = !pyObj || pyObj->d->validCppObject; + if (!result && throwPyError) + PyErr_Format(PyExc_RuntimeError, "Internal C++ object (%s) already deleted.", pyObj->ob_type->tp_name); + return result; +} + PyObject* newObject(SbkObjectType* instanceType, void* cptr, bool hasOwnership, diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index bab83a08..1abd43f4 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -253,7 +253,14 @@ LIBSHIBOKEN_API bool setCppPointer(SbkObject* sbkObj, PyTypeObject* desir /** * Returns false and sets a Python RuntimeError if the Python wrapper is not marked as valid. */ -LIBSHIBOKEN_API bool isValid(PyObject* wrapper); +LIBSHIBOKEN_API bool isValid(PyObject* pyObj); + +/** + * Returns false if the Python wrapper is not marked as valid. + * \param pyObj the object. + * \param throwPyError sets a Python RuntimeError when the object isn't valid. + */ +LIBSHIBOKEN_API bool isValid(SbkObject* pyObj, bool throwPyError = true); /** * Set the parent of \p child to \p parent. From dc0a3de17e9786037746cb02fb52e342f8cae34c Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Wed, 19 Jan 2011 11:20:29 -0300 Subject: [PATCH 220/564] Added test for module reloading. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed by Hugo Parente Reviewed by Renato Araújo --- tests/samplebinding/module_reload_test.py | 42 +++++++++++++++++++++ tests/samplebinding/test_module_template.py | 10 +++++ 2 files changed, 52 insertions(+) create mode 100644 tests/samplebinding/module_reload_test.py create mode 100644 tests/samplebinding/test_module_template.py diff --git a/tests/samplebinding/module_reload_test.py b/tests/samplebinding/module_reload_test.py new file mode 100644 index 00000000..1c870fc0 --- /dev/null +++ b/tests/samplebinding/module_reload_test.py @@ -0,0 +1,42 @@ +import os +import sys +import shutil +import unittest + +orig_path = os.path.join(os.path.dirname(__file__)) +workdir = os.getcwd() +src = os.path.join(orig_path, 'test_module_template.py') +dst = os.path.join(workdir, 'test_module.py') +shutil.copyfile(src, dst) +sys.path.append(workdir) + +def increment_module_value(): + modfile = open(dst, 'a') + modfile.write('MyOtherObjectType.value += 1' + os.linesep) + modfile.flush() + modfile.close() + os.remove(dst + 'c') + +class TestModuleReloading(unittest.TestCase): + + def testModuleReloading(self): + '''Test module reloading with on-the-fly modifications.''' + + import test_module + self.assertEqual(test_module.MyOtherObjectType.value, 10) + + increment_module_value() + reload(sys.modules['test_module']) + self.assertEqual(test_module.MyOtherObjectType.value, 11) + + reload(sys.modules['test_module']) + self.assertEqual(test_module.MyOtherObjectType.value, 11) + + increment_module_value() + reload(sys.modules['test_module']) + self.assertEqual(test_module.MyOtherObjectType.value, 12) + +if __name__ == "__main__": + unittest.main() + + diff --git a/tests/samplebinding/test_module_template.py b/tests/samplebinding/test_module_template.py new file mode 100644 index 00000000..b2e917de --- /dev/null +++ b/tests/samplebinding/test_module_template.py @@ -0,0 +1,10 @@ +from other import * +from sample import * + + +class MyObjectType(ObjectType): + pass + +class MyOtherObjectType(OtherObjectType): + value = 10 + From 3293847076330f07de9c70dd82f32bfeede6d317 Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Fri, 21 Jan 2011 10:21:16 -0300 Subject: [PATCH 221/564] Shiboken enums now have a tp_print representation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes the bug #611[1], and an unit test was also added. [1] http://bugs.openbossa.org/show_bug.cgi?id=611 Reviewed by Hugo Parente Reviewed by Luciano Wolf Reviewed by Renato Araújo --- libshiboken/sbkenum.cpp | 16 +++++++++++++++- tests/samplebinding/enum_test.py | 14 ++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/libshiboken/sbkenum.cpp b/libshiboken/sbkenum.cpp index 34a4b772..7aea88ad 100644 --- a/libshiboken/sbkenum.cpp +++ b/libshiboken/sbkenum.cpp @@ -36,14 +36,27 @@ struct SbkEnumObject PyObject* ob_name; }; +#define SBKENUMOBJECT_REPR_STRING "" + static PyObject* SbkEnumObject_repr(PyObject* self) { - return PyString_FromFormat("", + return PyString_FromFormat(SBKENUMOBJECT_REPR_STRING, self->ob_type->tp_name, PyString_AS_STRING(((SbkEnumObject*)self)->ob_name), ((SbkEnumObject*)self)->ob_ival); } +static int SbkEnumObject_print(PyObject* self, FILE* fp, int) +{ + Py_BEGIN_ALLOW_THREADS + fprintf(fp, SBKENUMOBJECT_REPR_STRING, + self->ob_type->tp_name, + PyString_AS_STRING(((SbkEnumObject*)self)->ob_name), + ((SbkEnumObject*)self)->ob_ival); + Py_END_ALLOW_THREADS + return 0; +} + static PyObject* SbkEnumObject_name(PyObject* self, void*) { Py_INCREF(((SbkEnumObject*)self)->ob_name); @@ -169,6 +182,7 @@ PyTypeObject* newType(const char* name) ::memset(type, 0, sizeof(PyTypeObject)); type->ob_type = &SbkEnumType_Type; type->tp_basicsize = sizeof(SbkEnumObject); + type->tp_print = &SbkEnumObject_print; type->tp_repr = &SbkEnumObject_repr; type->tp_str = &SbkEnumObject_repr; type->tp_flags = Py_TPFLAGS_DEFAULT; diff --git a/tests/samplebinding/enum_test.py b/tests/samplebinding/enum_test.py index 71ebef60..698287f9 100644 --- a/tests/samplebinding/enum_test.py +++ b/tests/samplebinding/enum_test.py @@ -26,6 +26,8 @@ '''Test cases for Python representation of C++ enums.''' +import os +import sys import unittest import sample @@ -83,6 +85,18 @@ def testAnonymousClassEnums(self): self.assertEqual(SampleNamespace.AnonymousClassEnum_Value0, 0) self.assertEqual(SampleNamespace.AnonymousClassEnum_Value1, 1) + def testEnumTpPrintImplementation(self): + '''Without SbkEnum.tp_print 'print' returns the enum represented as an int.''' + tmpfile = os.tmpfile() + sys.stdout = tmpfile + print Event.ANY_EVENT + sys.stdout = sys.__stdout__ + tmpfile.seek(0) + text = tmpfile.read().strip() + tmpfile.close() + self.assertEqual(text, str(Event.ANY_EVENT)) + self.assertEqual(text, repr(Event.ANY_EVENT)) + class EnumOverloadTest(unittest.TestCase): '''Test case for overloads involving enums''' From c584156614947a7345a82fcdd51ce542ce904407 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Fri, 21 Jan 2011 14:33:42 -0300 Subject: [PATCH 222/564] Updated apiextractor and generatorrunner version dependency. --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 52aea434..b20df0bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -include(icecc.cmake) +Include(icecc.cmake) project(shiboken) cmake_minimum_required(VERSION 2.6) @@ -7,8 +7,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules/ ${CMAKE_MODULE_PATH}) find_package(Qt4 4.5.0) -find_package(ApiExtractor 0.9.0) -find_package(GeneratorRunner 0.6.3) +find_package(ApiExtractor 0.9.3) +find_package(GeneratorRunner 0.6.4) find_package(PythonLibs) find_package(PythonInterpWithDebug) From 9fb7cf7616e8e9a8948edff1f203f35d2761a5db Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Fri, 21 Jan 2011 15:56:44 -0300 Subject: [PATCH 223/564] Update module version dependency. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b20df0bb..eb4372ce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,8 +7,8 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules/ ${CMAKE_MODULE_PATH}) find_package(Qt4 4.5.0) -find_package(ApiExtractor 0.9.3) -find_package(GeneratorRunner 0.6.4) +find_package(ApiExtractor 0.9.4) +find_package(GeneratorRunner 0.6.5) find_package(PythonLibs) find_package(PythonInterpWithDebug) From 63e2501545f8ef932414ae617f02fe73681e987c Mon Sep 17 00:00:00 2001 From: Hugo Parente Lima Date: Mon, 24 Jan 2011 10:23:30 -0200 Subject: [PATCH 224/564] Fix bug#636 - "Unable to navigate back to the main site from the generated documentation" --- doc/_themes/pysidedocs/layout.html | 2 +- doc/_themes/pysidedocs/static/pysidedocs.css | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/doc/_themes/pysidedocs/layout.html b/doc/_themes/pysidedocs/layout.html index eb574310..3115aa72 100644 --- a/doc/_themes/pysidedocs/layout.html +++ b/doc/_themes/pysidedocs/layout.html @@ -77,7 +77,7 @@