diff options
author | Hugo Lima <hugo.lima@openbossa.org> | 2010-02-12 18:18:50 -0200 |
---|---|---|
committer | Hugo Lima <hugo.lima@openbossa.org> | 2010-02-12 18:35:24 -0200 |
commit | 21151a2f4dc03ef6d62efcfb4a0f1f9d3dcb5183 (patch) | |
tree | 07c45ee29ccf4a2bfb216c00611f2369887c00ca | |
parent | fa5740279daa22be3c424c8fab4468447b3cbcaf (diff) |
Do not export Sbk*Type variables.
To access Sbk*Type variables from other modules, you need to use the array provided via CObjects.
Reviewed by Marcelo Lira <marcelo.lira@openbossa.org>
-rw-r--r-- | cppgenerator.cpp | 60 | ||||
-rw-r--r-- | headergenerator.cpp | 62 | ||||
-rw-r--r-- | headergenerator.h | 3 | ||||
-rw-r--r-- | libshiboken/basewrapper.cpp | 16 | ||||
-rw-r--r-- | libshiboken/basewrapper.h | 2 | ||||
-rw-r--r-- | shibokengenerator.cpp | 24 | ||||
-rw-r--r-- | shibokengenerator.h | 3 |
7 files changed, 136 insertions, 34 deletions
diff --git a/cppgenerator.cpp b/cppgenerator.cpp index 708114076..bd4faea33 100644 --- a/cppgenerator.cpp +++ b/cppgenerator.cpp @@ -635,11 +635,13 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun s << INDENT << "SbkBaseWrapper* sbkSelf = reinterpret_cast<SbkBaseWrapper*>(self);" << endl; s << INDENT << "assert(!sbkSelf->cptr);\n"; // FIXME: object reinitialization not supported - if (metaClass->isAbstract() || metaClass->baseClassNames().size() > 1) + if (metaClass->isAbstract() || metaClass->baseClassNames().size() > 1) { s << INDENT << "SbkBaseWrapperType* type = reinterpret_cast<SbkBaseWrapperType*>(self->ob_type);" << endl; + s << INDENT << "SbkBaseWrapperType* myType = reinterpret_cast<SbkBaseWrapperType*>(" << cpythonTypeNameExt(metaClass->typeEntry()) << ");" << endl; + } if (metaClass->isAbstract()) { - s << INDENT << "if (type == &" << className << ") {" << endl; + s << INDENT << "if (type == myType) {" << endl; { Indentation indent(INDENT); s << INDENT << "PyErr_SetString(PyExc_NotImplementedError," << endl; @@ -655,13 +657,13 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun if (metaClass->baseClassNames().size() > 1) { if (!metaClass->isAbstract()) { - s << INDENT << "if (type != &" << className << ") {" << endl; + s << INDENT << "if (type != myType) {" << endl; } { Indentation indentation(INDENT); - s << INDENT << "type->mi_init = " << className << ".mi_init;" << endl; - s << INDENT << "type->mi_offsets = " << className << ".mi_offsets;" << endl; - s << INDENT << "type->mi_specialcast = " << className << ".mi_specialcast;" << endl; + 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; } if (!metaClass->isAbstract()) s << INDENT << '}' << endl << endl; @@ -1609,7 +1611,7 @@ void CppGenerator::writeSpecialCastFunction(QTextStream& s, const AbstractMetaCl AbstractMetaClassList bases = getBaseClasses(metaClass); bool firstClass = true; foreach(const AbstractMetaClass* baseClass, bases) { - s << INDENT << (!firstClass ? "else " : "") << "if (desiredType == &" << cpythonTypeName(baseClass) << ")\n"; + s << INDENT << (!firstClass ? "else " : "") << "if (desiredType == reinterpret_cast<SbkBaseWrapperType*>(" << cpythonTypeNameExt(baseClass->typeEntry()) << "))\n"; Indentation indent(INDENT); s << INDENT << "return static_cast<" << baseClass->qualifiedCppName() << "*>(me);\n"; firstClass = false; @@ -1655,7 +1657,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* QString mi_specialcast('0'); QString cppClassName = metaClass->qualifiedCppName(); QString className = cpythonTypeName(metaClass).replace(QRegExp("_Type$"), ""); - QString baseClassName("(PyTypeObject*)&"); + QString baseClassName('0'); if (metaClass->hasArithmeticOperatorOverload() || metaClass->hasLogicalOperatorOverload() @@ -1667,10 +1669,8 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* if (supportsSequenceProtocol(metaClass)) tp_as_sequence = QString("&Py%1_as_sequence").arg(cppClassName); - if (metaClass->baseClass()) - baseClassName.append(cpythonTypeName(metaClass->baseClass()->typeEntry())); - else - baseClassName.append("Shiboken::SbkBaseWrapper_Type"); + if (!metaClass->baseClass()) + baseClassName = "reinterpret_cast<PyTypeObject*>(&Shiboken::SbkBaseWrapper_Type)"; if (metaClass->isNamespace() || metaClass->hasPrivateDestructor()) { tp_flags = "Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES"; @@ -1735,7 +1735,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* s << "// Class Definition -----------------------------------------------" << endl; - s << "Shiboken::SbkBaseWrapperType " << className + "_Type" << " = { { {" << endl; + s << "static SbkBaseWrapperType " << className + "_Type" << " = { { {" << endl; s << INDENT << "PyObject_HEAD_INIT(&Shiboken::SbkBaseWrapperType_Type)" << endl; s << INDENT << "/*ob_size*/ 0," << endl; s << INDENT << "/*tp_name*/ \"" << cppClassName << "\"," << endl; @@ -2149,7 +2149,7 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu } 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; @@ -2163,6 +2163,7 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu 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; @@ -2241,7 +2242,7 @@ void CppGenerator::writeEnumDefinition(QTextStream& s, const AbstractMetaEnum* c s << INDENT << "{0} // Sentinel" << endl; s << "};" << endl << endl; - s << "PyTypeObject " << cpythonName << "_Type = {" << endl; + s << "static PyTypeObject " << cpythonName << "_Type = {" << endl; s << INDENT << "PyObject_HEAD_INIT(&PyType_Type)" << endl; s << INDENT << "/*ob_size*/ 0," << endl; s << INDENT << "/*tp_name*/ \"" << cppEnum->name() << "\"," << endl; @@ -2361,11 +2362,11 @@ void CppGenerator::writeFlagsDefinition(QTextStream& s, const AbstractMetaEnum* QString cpythonName = cpythonFlagsName(flagsEntry); QString enumName = cpythonEnumName(cppEnum); - QString newFunc = QString("(newfunc)") + cpythonName + "_New"; - writeFlagsNewMethod(s, flagsEntry); - s << endl; + QString newFunc = cpythonName + "_New"; - s << "PyTypeObject " << cpythonName << "_Type = {" << endl; + 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(&PyType_Type)" << endl; s << INDENT << "/*ob_size*/ 0," << endl; s << INDENT << "/*tp_name*/ \"" << flagsEntry->flagsName() << "\"," << endl; @@ -2413,6 +2414,9 @@ void CppGenerator::writeFlagsDefinition(QTextStream& s, const AbstractMetaEnum* s << INDENT << "/*tp_subclasses*/ 0," << endl; s << INDENT << "/*tp_weaklist*/ 0" << endl; s << "};" << endl << endl; + + writeFlagsNewMethod(s, flagsEntry); + s << endl; } void CppGenerator::writeFlagsBinaryOperator(QTextStream& s, const AbstractMetaEnum* cppEnum, @@ -2480,12 +2484,17 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m s << "init_" << metaClass->qualifiedCppName().replace("::", "_") << "(PyObject* module)" << endl; s << '{' << endl; + if (!metaClass->isNamespace()) + s << INDENT << cpythonTypeNameExt(metaClass->typeEntry()) << " = reinterpret_cast<PyTypeObject*>(&" << cpythonTypeName(metaClass->typeEntry()) << ");" << endl << endl; + // class inject-code target/beginning if (!metaClass->typeEntry()->codeSnips().isEmpty()) { writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), CodeSnip::Beginning, TypeSystem::TargetLangCode, 0, 0, metaClass); s << endl; } + if (metaClass->baseClass()) + s << INDENT << pyTypeName << ".super.ht_type.tp_base = " << cpythonTypeNameExt(metaClass->baseClass()->typeEntry()) << ';' << endl; // Multiple inheritance if (metaClass->baseClassNames().size() > 1) { AbstractMetaClassList baseClasses = getBaseClasses(metaClass); @@ -2494,7 +2503,7 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m s << ',' << endl; QStringList bases; foreach (const AbstractMetaClass* base, baseClasses) - bases << QString("(PyTypeObject*)&%1").arg(cpythonTypeName(base->typeEntry())); + bases << "(PyTypeObject*)"+cpythonTypeNameExt(base->typeEntry()); Indentation indent(INDENT); s << INDENT << bases.join(", ") << ");" << endl << endl; } @@ -2777,6 +2786,10 @@ void CppGenerator::finishGeneration() } } + s << "PyTypeObject** " << cppApiVariableName() << ";" << endl << endl;; + foreach (const QString& requiredModule, TypeDatabase::instance()->requiredTargetImports()) + s << "PyTypeObject** " << cppApiVariableName(requiredModule) << ";" << endl << endl;; + s << "// Module initialization "; s << "------------------------------------------------------------" << endl; s << "extern \"C\" {" << endl << endl; @@ -2791,7 +2804,7 @@ void CppGenerator::finishGeneration() } foreach (const QString& requiredModule, TypeDatabase::instance()->requiredTargetImports()) { - s << INDENT << "if (PyImport_ImportModule(\"" << requiredModule << "\") == NULL) {" << endl; + s << INDENT << "if (!Shiboken::importModule(\"" << requiredModule << "\", &" << cppApiVariableName(requiredModule) << ")) {" << endl; s << INDENT << INDENT << "PyErr_SetString(PyExc_ImportError," << "\"could not import "; s << requiredModule << "\");" << endl << INDENT << INDENT << "return;" << endl; s << INDENT << "}" << endl << endl; @@ -2801,6 +2814,11 @@ void CppGenerator::finishGeneration() s << INDENT << "PyObject* module = Py_InitModule(\"" << moduleName() << "\", "; s << moduleName() << "_methods);" << endl << endl; + s << INDENT << "// Create a CObject containing the API pointer array's address" << endl; + s << INDENT << "static PyTypeObject* cppApi[" << "SBK_" << moduleName() << "_IDX_COUNT" << "];" << endl; + s << INDENT << cppApiVariableName() << " = cppApi;" << endl; + s << INDENT << "PyObject* cppApiObject = PyCObject_FromVoidPtr(reinterpret_cast<void*>(cppApi), 0);" << endl; + s << INDENT << "PyModule_AddObject(module, \"_Cpp_Api\", cppApiObject);" << endl << endl; s << INDENT << "// Initialize classes in the type system" << endl; s << classPythonDefines << endl; diff --git a/headergenerator.cpp b/headergenerator.cpp index f5765ed2c..9d483bedc 100644 --- a/headergenerator.cpp +++ b/headergenerator.cpp @@ -143,17 +143,11 @@ void HeaderGenerator::writeFunction(QTextStream& s, const AbstractMetaFunction* void HeaderGenerator::writeTypeCheckMacro(QTextStream& s, const TypeEntry* type) { - QString pyTypeName = cpythonTypeName(type); + QString pyTypeName = cppApiVariableName() + '[' + getTypeIndexVariableName(type) + ']'; QString checkFunction = cpythonCheckFunction(type); - s << getApiExportMacro() << " PyAPI_DATA("; - if (type->isObject() || type->isValue()) - s << "Shiboken::SbkBaseWrapperType"; - else - s << "PyTypeObject"; - s << ") " << pyTypeName << ';' << endl; - s << "#define " << checkFunction << "(op) PyObject_TypeCheck(op, (PyTypeObject*)&"; + s << "#define " << checkFunction << "(op) PyObject_TypeCheck(op, (PyTypeObject*)"; s << pyTypeName << ')' << endl; - s << "#define " << checkFunction << "Exact(op) ((op)->ob_type == (PyTypeObject*)&"; + s << "#define " << checkFunction << "Exact(op) ((op)->ob_type == (PyTypeObject*)"; s << pyTypeName << ')' << endl; } @@ -188,8 +182,38 @@ void HeaderGenerator::writeTypeConverterDecl(QTextStream& s, const TypeEntry* ty s << "};" << endl; } +void HeaderGenerator::writeTypeIndexDefineLine(QTextStream& s, const TypeEntry* typeEntry, int& idx) +{ + if (!typeEntry || !typeEntry->generateCode()) + return; + s.setFieldAlignment(QTextStream::AlignLeft); + s << "#define "; + s.setFieldWidth(60); + s << getTypeIndexVariableName(typeEntry); + s.setFieldWidth(0); + s << ' ' << (idx++) << endl; + if (typeEntry->isEnum()) { + const EnumTypeEntry* ete = reinterpret_cast<const EnumTypeEntry*>(typeEntry); + if (ete->flags()) + writeTypeIndexDefineLine(s, ete->flags(), idx); + } +} + +void HeaderGenerator::writeTypeIndexDefine(QTextStream& s, const AbstractMetaClass* metaClass, int& idx) +{ + if (!metaClass->typeEntry()->generateCode()) + return; + if (!metaClass->isNamespace()) + writeTypeIndexDefineLine(s, metaClass->typeEntry(), idx); + foreach (const AbstractMetaEnum* metaEnum, metaClass->enums()) + writeTypeIndexDefineLine(s, metaEnum->typeEntry(), idx); +} + void HeaderGenerator::finishGeneration() { + if (classes().isEmpty()) + return; + // Generate the main header for this module. // This header should be included by binding modules // extendind on top of this one. @@ -205,7 +229,19 @@ void HeaderGenerator::finishGeneration() Indentation indent(INDENT); - s_pts << endl << "// Global enums" << endl; + s_pts << "// Type indices" << endl; + int idx = 0; + foreach (const AbstractMetaClass* metaClass, classes()) + writeTypeIndexDefine(s_pts, metaClass, idx); + foreach (const AbstractMetaEnum* metaEnum, globalEnums()) + writeTypeIndexDefineLine(s_pts, metaEnum->typeEntry(), idx); + s_pts << "#define "; + s_pts.setFieldWidth(60); + s_pts << "SBK_"+moduleName()+"_IDX_COUNT"; + s_pts.setFieldWidth(0); + s_pts << ' ' << idx << endl << endl; + s_pts << "extern PyTypeObject** " << cppApiVariableName() << ';' << endl << endl; + foreach (const AbstractMetaEnum* cppEnum, globalEnums()) { QString incFile = cppEnum->includeFile().split(QDir::separator()).takeLast(); if (!incFile.isEmpty()) @@ -381,19 +417,19 @@ void HeaderGenerator::writeSbkTypeFunction(QTextStream& s, const AbstractMetaEnu if (cppEnum->enclosingClass()) enumPrefix = cppEnum->enclosingClass()->qualifiedCppName() + "::"; s << "template<>\ninline PyTypeObject* SbkType<" << enumPrefix << cppEnum->name() << " >() " - << "{ return &" << cpythonTypeName(cppEnum->typeEntry()) << "; }\n"; + << "{ return " << cpythonTypeNameExt(cppEnum->typeEntry()) << "; }\n"; FlagsTypeEntry* flag = cppEnum->typeEntry()->flags(); if (flag) { s << "template<>\ninline PyTypeObject* SbkType<" << flag->name() << " >() " - << "{ return &" << cpythonTypeName(flag) << "; }\n"; + << "{ return " << cpythonTypeNameExt(flag) << "; }\n"; } } void HeaderGenerator::writeSbkTypeFunction(QTextStream& s, const AbstractMetaClass* cppClass) { s << "template<>\ninline PyTypeObject* SbkType<" << cppClass->qualifiedCppName() << " >() " - << "{ return reinterpret_cast<PyTypeObject*>(&" << cpythonTypeName(cppClass) << "); }\n"; + << "{ return reinterpret_cast<PyTypeObject*>(" << cpythonTypeNameExt(cppClass->typeEntry()) << "); }\n"; } void HeaderGenerator::writeSbkCopyCppObjectFunction(QTextStream& s, const AbstractMetaClass* metaClass) diff --git a/headergenerator.h b/headergenerator.h index ad1e3bd97..67791999c 100644 --- a/headergenerator.h +++ b/headergenerator.h @@ -47,6 +47,9 @@ private: 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); + }; #endif // HEADERGENERATOR_H diff --git a/libshiboken/basewrapper.cpp b/libshiboken/basewrapper.cpp index 2dda3a4bc..dc86fa831 100644 --- a/libshiboken/basewrapper.cpp +++ b/libshiboken/basewrapper.cpp @@ -196,6 +196,22 @@ void SbkBaseWrapper_clearReferences(SbkBaseWrapper* self) delete self->referredObjects; } +bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr) +{ + Shiboken::AutoDecRef module(PyImport_ImportModule(moduleName)); + if (module.isNull()) + return false; + + Shiboken::AutoDecRef cppApi(PyObject_GetAttrString(module, "_Cpp_Api")); + if (cppApi.isNull()) + return false; + + if (PyCObject_Check(cppApi)) + *cppApiPtr = reinterpret_cast<PyTypeObject**>(PyCObject_AsVoidPtr(cppApi)); + + return true; +} + // Wrapper metatype and base type ---------------------------------------------------------- extern "C" diff --git a/libshiboken/basewrapper.h b/libshiboken/basewrapper.h index 7d834da0e..e8ea7cc1b 100644 --- a/libshiboken/basewrapper.h +++ b/libshiboken/basewrapper.h @@ -256,6 +256,8 @@ void SbkBaseWrapper_Dealloc(PyObject* self) LIBSHIBOKEN_API PyAPI_FUNC(void) SbkBaseWrapper_Dealloc_PrivateDtor(PyObject* self); +LIBSHIBOKEN_API bool importModule(const char* moduleName, PyTypeObject*** cppApiPtr); + } // namespace Shiboken #endif // BASEWRAPPER_H diff --git a/shibokengenerator.cpp b/shibokengenerator.cpp index f94155e9c..dfb2a7c92 100644 --- a/shibokengenerator.cpp +++ b/shibokengenerator.cpp @@ -460,6 +460,11 @@ QString ShibokenGenerator::cpythonTypeName(const TypeEntry* type) return cpythonBaseName(type) + "_Type"; } +QString ShibokenGenerator::cpythonTypeNameExt(const TypeEntry* type) +{ + return cppApiVariableName(type->targetLangPackage()) + '[' + getTypeIndexVariableName(type) + ']'; +} + QString ShibokenGenerator::cpythonOperatorFunctionName(const AbstractMetaFunction* func) { if (!func->isOperatorOverload()) @@ -1308,3 +1313,22 @@ bool ShibokenGenerator::usePySideExtensions() const return m_usePySideExtensions; } +QString ShibokenGenerator::cppApiVariableName(const QString& moduleName) const +{ + QString result = moduleName.isEmpty() ? ShibokenGenerator::packageName() : moduleName; + result.replace(".", "_"); + result.prepend("Sbk"); + result.append("Types"); + return result; +} + +QString ShibokenGenerator::getTypeIndexVariableName(const TypeEntry* metaType) +{ + QString res("SBK_"); + res += metaType->qualifiedCppName(); + res.replace("::", "_"); + res.replace("<", "_"); + res.replace(">", "_"); + res += "_IDX"; + return res.toUpper(); +} diff --git a/shibokengenerator.h b/shibokengenerator.h index cae9943b1..edddbbc66 100644 --- a/shibokengenerator.h +++ b/shibokengenerator.h @@ -234,6 +234,7 @@ public: QString cpythonBaseName(const AbstractMetaType* type); QString cpythonTypeName(const AbstractMetaClass* metaClass); QString cpythonTypeName(const TypeEntry* type); + QString cpythonTypeNameExt(const TypeEntry* type); QString cpythonCheckFunction(const TypeEntry* type, bool genericNumberType = false, bool checkExact = false); QString cpythonCheckFunction(const AbstractMetaType* metaType, bool genericNumberType = false, bool checkExact = false); QString guessCPythonCheckFunction(const QString& type); @@ -286,6 +287,8 @@ public: bool useReturnValueHeuristic() const; /// Returns true if the user enabled PySide extensions. bool usePySideExtensions() const; + QString cppApiVariableName(const QString& moduleName = QString()) const; + QString getTypeIndexVariableName(const TypeEntry* metaType); protected: bool doSetup(const QMap<QString, QString>& args); // verify whether the class is copyable |