aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHugo Lima <hugo.lima@openbossa.org>2010-02-12 18:18:50 -0200
committerHugo Lima <hugo.lima@openbossa.org>2010-02-12 18:35:24 -0200
commit21151a2f4dc03ef6d62efcfb4a0f1f9d3dcb5183 (patch)
tree07c45ee29ccf4a2bfb216c00611f2369887c00ca
parentfa5740279daa22be3c424c8fab4468447b3cbcaf (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.cpp60
-rw-r--r--headergenerator.cpp62
-rw-r--r--headergenerator.h3
-rw-r--r--libshiboken/basewrapper.cpp16
-rw-r--r--libshiboken/basewrapper.h2
-rw-r--r--shibokengenerator.cpp24
-rw-r--r--shibokengenerator.h3
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