aboutsummaryrefslogtreecommitdiffstats
path: root/generator
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2017-01-12 13:05:56 +0100
committerChristian Tismer <tismer@stackless.com>2017-03-17 15:34:50 +0000
commit4d76c6e2c9870ce3928425682e7f091396592206 (patch)
tree1ce3c7d28b44653859fa651abb711bd5476f58a1 /generator
parent2ab4062e9d07a821e4d205dde7dead85e4c69161 (diff)
Implement partial QSharedPointer support
This change introduces a new XML tag called smart-pointer-type which currently only supports implementations of C++ shared pointers. This allows using objects pointed to by a shared pointer inside python code. There is one known limitation at the moment. Python shared pointer objects are only created as a result of using C++ API with shared pointers in the method signature (either the return type or argument type). Thus is it is not currently possible to instantiate shared pointer objects directly, e.g. p = ModuleName.SharedPointer() will not work. Task-number: PYSIDE-454 Change-Id: Iacf9fcc8613fbf9bd94e179169d78da8aac58f45 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Christian Tismer <tismer@stackless.com>
Diffstat (limited to 'generator')
-rw-r--r--generator/generator.cpp175
-rw-r--r--generator/generator.h70
-rw-r--r--generator/qtdoc/qtdocgenerator.cpp21
-rw-r--r--generator/qtdoc/qtdocgenerator.h5
-rw-r--r--generator/shiboken2/cppgenerator.cpp582
-rw-r--r--generator/shiboken2/cppgenerator.h84
-rw-r--r--generator/shiboken2/headergenerator.cpp66
-rw-r--r--generator/shiboken2/headergenerator.h6
-rw-r--r--generator/shiboken2/overloaddata.cpp2
-rw-r--r--generator/shiboken2/shibokengenerator.cpp35
-rw-r--r--generator/shiboken2/shibokengenerator.h7
11 files changed, 812 insertions, 241 deletions
diff --git a/generator/generator.cpp b/generator/generator.cpp
index 772ab43..e4d27c0 100644
--- a/generator/generator.cpp
+++ b/generator/generator.cpp
@@ -47,14 +47,19 @@ struct Generator::GeneratorPrivate {
QString packageName;
int numGenerated;
QStringList instantiatedContainersNames;
- QList<const AbstractMetaType*> instantiatedContainers;
+ QStringList instantiatedSmartPointerNames;
+ QList<const AbstractMetaType *> instantiatedContainers;
+ QList<const AbstractMetaType *> instantiatedSmartPointers;
+
};
Generator::Generator() : m_d(new GeneratorPrivate)
{
m_d->numGenerated = 0;
- m_d->instantiatedContainers = QList<const AbstractMetaType*>();
+ m_d->instantiatedContainers = QList<const AbstractMetaType *>();
+ m_d->instantiatedSmartPointers = QList<const AbstractMetaType *>();
m_d->instantiatedContainersNames = QStringList();
+ m_d->instantiatedSmartPointerNames = QStringList();
}
Generator::~Generator()
@@ -82,16 +87,17 @@ bool Generator::setup(const ApiExtractor& extractor, const QMap< QString, QStrin
else
qCWarning(lcShiboken) << "Couldn't find the package name!!";
- collectInstantiatedContainers();
+ collectInstantiatedContainersAndSmartPointers();
return doSetup(args);
}
QString Generator::getSimplifiedContainerTypeName(const AbstractMetaType* type)
{
- if (!type->typeEntry()->isContainer())
- return type->cppSignature();
- QString typeName = type->cppSignature();
+ const QString signature = type->cppSignature();
+ if (!type->typeEntry()->isContainer() && !type->typeEntry()->isSmartPointer())
+ return signature;
+ QString typeName = signature;
if (type->isConstant())
typeName.remove(0, sizeof("const ") / sizeof(char) - 1);
switch (type->referenceType()) {
@@ -109,18 +115,21 @@ QString Generator::getSimplifiedContainerTypeName(const AbstractMetaType* type)
return typeName;
}
-void Generator::addInstantiatedContainers(const AbstractMetaType *type, const QString &context)
+void Generator::addInstantiatedContainersAndSmartPointers(const AbstractMetaType *type,
+ const QString &context)
{
if (!type)
return;
foreach (const AbstractMetaType* t, type->instantiations())
- addInstantiatedContainers(t, context);
- if (!type->typeEntry()->isContainer())
+ addInstantiatedContainersAndSmartPointers(t, context);
+ if (!type->typeEntry()->isContainer() && !type->typeEntry()->isSmartPointer())
return;
+ bool isContainer = type->typeEntry()->isContainer();
if (type->hasTemplateChildren()) {
+ QString piece = isContainer ? QStringLiteral("container") : QStringLiteral("smart pointer");
QString warning =
- QString::fromLatin1("Skipping instantiation of container '%1' because it has template"
- " arguments.").arg(type->originalTypeDescription());
+ QString::fromLatin1("Skipping instantiation of %1 '%2' because it has template"
+ " arguments.").arg(piece).arg(type->originalTypeDescription());
if (!context.isEmpty())
warning.append(QStringLiteral(" Calling context: %1").arg(context));
@@ -129,37 +138,46 @@ void Generator::addInstantiatedContainers(const AbstractMetaType *type, const QS
}
QString typeName = getSimplifiedContainerTypeName(type);
- if (!m_d->instantiatedContainersNames.contains(typeName)) {
- m_d->instantiatedContainersNames.append(typeName);
- m_d->instantiatedContainers.append(type);
+ if (isContainer) {
+ if (!m_d->instantiatedContainersNames.contains(typeName)) {
+ m_d->instantiatedContainersNames.append(typeName);
+ m_d->instantiatedContainers.append(type);
+ }
+ } else {
+ // Is smart pointer.
+ if (!m_d->instantiatedSmartPointerNames.contains(typeName)) {
+ m_d->instantiatedSmartPointerNames.append(typeName);
+ m_d->instantiatedSmartPointers.append(type);
+ }
}
+
}
-void Generator::collectInstantiatedContainers(const AbstractMetaFunction* func)
+void Generator::collectInstantiatedContainersAndSmartPointers(const AbstractMetaFunction *func)
{
- addInstantiatedContainers(func->type(), func->signature());
+ addInstantiatedContainersAndSmartPointers(func->type(), func->signature());
foreach (const AbstractMetaArgument* arg, func->arguments())
- addInstantiatedContainers(arg->type(), func->signature());
+ addInstantiatedContainersAndSmartPointers(arg->type(), func->signature());
}
-void Generator::collectInstantiatedContainers(const AbstractMetaClass* metaClass)
+void Generator::collectInstantiatedContainersAndSmartPointers(const AbstractMetaClass *metaClass)
{
if (!metaClass->typeEntry()->generateCode())
return;
foreach (const AbstractMetaFunction* func, metaClass->functions())
- collectInstantiatedContainers(func);
+ collectInstantiatedContainersAndSmartPointers(func);
foreach (const AbstractMetaField* field, metaClass->fields())
- addInstantiatedContainers(field->type(), field->name());
+ addInstantiatedContainersAndSmartPointers(field->type(), field->name());
foreach (AbstractMetaClass* innerClass, metaClass->innerClasses())
- collectInstantiatedContainers(innerClass);
+ collectInstantiatedContainersAndSmartPointers(innerClass);
}
-void Generator::collectInstantiatedContainers()
+void Generator::collectInstantiatedContainersAndSmartPointers()
{
foreach (const AbstractMetaFunction* func, globalFunctions())
- collectInstantiatedContainers(func);
+ collectInstantiatedContainersAndSmartPointers(func);
foreach (const AbstractMetaClass* metaClass, classes())
- collectInstantiatedContainers(metaClass);
+ collectInstantiatedContainersAndSmartPointers(metaClass);
}
QList<const AbstractMetaType*> Generator::instantiatedContainers() const
@@ -167,6 +185,11 @@ QList<const AbstractMetaType*> Generator::instantiatedContainers() const
return m_d->instantiatedContainers;
}
+QList<const AbstractMetaType*> Generator::instantiatedSmartPointers() const
+{
+ return m_d->instantiatedSmartPointers;
+}
+
QMap< QString, QString > Generator::options() const
{
return QMap<QString, QString>();
@@ -278,37 +301,68 @@ inline void touchFile(const QString &filePath)
toucher.close();
}
-bool Generator::generate()
+bool Generator::generateFileForContext(GeneratorContext &context)
{
- foreach (AbstractMetaClass *cls, m_d->apiextractor->classes()) {
- if (!shouldGenerate(cls))
- continue;
+ AbstractMetaClass *cls = context.metaClass();
- QString fileName = fileNameForClass(cls);
- if (fileName.isNull())
- continue;
- if (ReportHandler::isDebug(ReportHandler::SparseDebug))
- qCDebug(lcShiboken) << "generating: " << fileName;
+ if (!shouldGenerate(cls))
+ return true;
+
+ const QString fileName = fileNameForContext(context);
+ if (fileName.isEmpty())
+ return true;
+ if (ReportHandler::isDebug(ReportHandler::SparseDebug))
+ qCDebug(lcShiboken) << "generating: " << fileName;
- QString filePath = outputDirectory() + QLatin1Char('/') + subDirectoryForClass(cls)
- + QLatin1Char('/') + fileName;
- FileOut fileOut(filePath);
- generateClass(fileOut.stream, cls);
+ QString filePath = outputDirectory() + QLatin1Char('/') + subDirectoryForClass(cls)
+ + QLatin1Char('/') + fileName;
+ FileOut fileOut(filePath);
- FileOut::State state = fileOut.done();
- switch (state) {
- case FileOut::Failure:
+ generateClass(fileOut.stream, context);
+
+ FileOut::State state = fileOut.done();
+ switch (state) {
+ case FileOut::Failure:
+ return false;
+ case FileOut::Unchanged:
+ // Even if contents is unchanged, the last file modification time should be updated,
+ // so that the build system can rely on the fact the generated file is up-to-date.
+ touchFile(filePath);
+ break;
+ case FileOut::Success:
+ break;
+ }
+
+ ++m_d->numGenerated;
+ return true;
+}
+
+QString Generator::getFileNameBaseForSmartPointer(const AbstractMetaType *smartPointerType,
+ const AbstractMetaClass *smartPointerClass) const
+{
+ const AbstractMetaType *innerType = smartPointerType->getSmartPointerInnerType();
+ QString fileName = smartPointerClass->qualifiedCppName().toLower();
+ fileName.replace(QLatin1String("::"), QLatin1String("_"));
+ fileName.append(QLatin1String("_"));
+ fileName.append(innerType->name().toLower());
+
+ return fileName;
+}
+
+bool Generator::generate()
+{
+ foreach (AbstractMetaClass *cls, m_d->apiextractor->classes()) {
+ GeneratorContext context(cls);
+ if (!generateFileForContext(context))
return false;
- case FileOut::Unchanged:
- // Even if contents is unchanged, the last file modification time should be updated,
- // so that the build system can rely on the fact the generated file is up-to-date.
- touchFile(filePath);
- break;
- case FileOut::Success:
- break;
- }
+ }
- ++m_d->numGenerated;
+ foreach (const AbstractMetaType *type, instantiatedSmartPointers()) {
+ AbstractMetaClass *smartPointerClass =
+ AbstractMetaClass::findClass(m_d->apiextractor->smartPointers(), type->name());
+ GeneratorContext context(smartPointerClass, type, true);
+ if (!generateFileForContext(context))
+ return false;
}
return finishGeneration();
}
@@ -770,3 +824,26 @@ QString getClassTargetFullName(const AbstractMetaEnum* metaEnum, bool includePac
{
return getClassTargetFullName_(metaEnum, includePackageName);
}
+
+QString getClassTargetFullName(const AbstractMetaType *metaType, bool includePackageName)
+{
+ QString name = metaType->cppSignature();
+ name.replace(QLatin1String("::"), QLatin1String("_"));
+ name.replace(QLatin1Char('<'), QLatin1Char('_'));
+ name.remove(QLatin1Char('>'));
+ name.remove(QLatin1Char(' '));
+ if (includePackageName) {
+ name.prepend(QLatin1Char('.'));
+ name.prepend(metaType->package());
+ }
+ return name;
+}
+
+QString getFilteredCppSignatureString(QString signature)
+{
+ signature.replace(QLatin1String("::"), QLatin1String("_"));
+ signature.replace(QLatin1Char('<'), QLatin1Char('_'));
+ signature.replace(QLatin1Char('>'), QLatin1Char('_'));
+ signature.replace(QLatin1Char(' '), QLatin1Char('_'));
+ return signature;
+}
diff --git a/generator/generator.h b/generator/generator.h
index ac78d62..386b9d5 100644
--- a/generator/generator.h
+++ b/generator/generator.h
@@ -60,6 +60,44 @@ void verifyDirectoryFor(const QFile &file);
QString getClassTargetFullName(const AbstractMetaClass* metaClass, bool includePackageName = true);
QString getClassTargetFullName(const AbstractMetaEnum* metaEnum, bool includePackageName = true);
+QString getClassTargetFullName(const AbstractMetaType *metaType, bool includePackageName = true);
+QString getFilteredCppSignatureString(QString signature);
+
+
+/**
+ * A GeneratorContext object contains a pointer to an AbstractMetaClass and/or a specialized
+ * AbstractMetaType, for which code is currently being generated.
+ *
+ * The main case is when the context contains only an AbstractMetaClass pointer, which is used
+ * by different methods to generate appropriate expressions, functions, type names, etc.
+ *
+ * The second case is for generation of code for smart pointers. In this case the m_metaClass member
+ * contains the generic template class of the smart pointer, and the m_preciseClassType member
+ * contains the instantiated template type, e.g. a concrete shared_ptr<int>. To
+ * distinguish this case, the member m_forSmartPointer is set to true.
+ *
+ * In the future the second case might be generalized for all template type instantiations.
+ */
+class GeneratorContext {
+public:
+ GeneratorContext() : m_metaClass(0), m_preciseClassType(0), m_forSmartPointer(false) {}
+ GeneratorContext(AbstractMetaClass *metaClass,
+ const AbstractMetaType *preciseType = 0,
+ bool forSmartPointer = false)
+ : m_metaClass(metaClass),
+ m_preciseClassType(preciseType),
+ m_forSmartPointer(forSmartPointer) {}
+
+
+ AbstractMetaClass *metaClass() const { return m_metaClass; }
+ bool forSmartPointer() const { return m_forSmartPointer; }
+ const AbstractMetaType *preciseType() const { return m_preciseClassType; }
+
+private:
+ AbstractMetaClass *m_metaClass;
+ const AbstractMetaType *m_preciseClassType;
+ bool m_forSmartPointer;
+};
/**
* Base class for all generators. The default implementations does nothing,
@@ -161,6 +199,14 @@ public:
*/
bool generate();
+
+ /// Generates a file for given AbstractMetaClass or AbstractMetaType (smart pointer case).
+ bool generateFileForContext(GeneratorContext &context);
+
+ /// Returns the file base name for a smart pointer.
+ QString getFileNameBaseForSmartPointer(const AbstractMetaType *smartPointerType,
+ const AbstractMetaClass *smartPointerClass) const;
+
/// Returns the number of generated items
int numGenerated() const;
@@ -278,14 +324,16 @@ public:
QString minimalConstructor(const TypeEntry* type) const;
QString minimalConstructor(const AbstractMetaType* type) const;
QString minimalConstructor(const AbstractMetaClass* metaClass) const;
+
protected:
/**
- * Returns the file name used to write the binding code of an AbstractMetaClass.
- * \param metaClass the AbstractMetaClass for which the file name must be
- * returned
+ * Returns the file name used to write the binding code of an AbstractMetaClass/Type.
+ * \param context the GeneratorContext which contains an AbstractMetaClass or AbstractMetaType
+ * for which the file name must be returned
* \return the file name used to write the binding code for the class
*/
- virtual QString fileNameForClass(const AbstractMetaClass* metaClass) const = 0;
+ virtual QString fileNamePrefix() const = 0;
+ virtual QString fileNameForContext(GeneratorContext &context) const = 0;
virtual bool doSetup(const QMap<QString, QString>& args) = 0;
@@ -296,7 +344,7 @@ protected:
* \param s text stream to write the generated output
* \param metaClass the class that should be generated
*/
- virtual void generateClass(QTextStream& s, const AbstractMetaClass* metaClass) = 0;
+ virtual void generateClass(QTextStream& s, GeneratorContext &classContext) = 0;
virtual bool finishGeneration() = 0;
/**
@@ -311,16 +359,18 @@ protected:
virtual QString subDirectoryForPackage(QString packageName = QString()) const;
QList<const AbstractMetaType*> instantiatedContainers() const;
+ QList<const AbstractMetaType*> instantiatedSmartPointers() const;
- static QString getSimplifiedContainerTypeName(const AbstractMetaType* type);
- void addInstantiatedContainers(const AbstractMetaType *type, const QString &context);
+ static QString getSimplifiedContainerTypeName(const AbstractMetaType *type);
+ void addInstantiatedContainersAndSmartPointers(const AbstractMetaType *type,
+ const QString &context);
private:
struct GeneratorPrivate;
GeneratorPrivate* m_d;
- void collectInstantiatedContainers(const AbstractMetaFunction* func);
- void collectInstantiatedContainers(const AbstractMetaClass* metaClass);
- void collectInstantiatedContainers();
+ void collectInstantiatedContainersAndSmartPointers(const AbstractMetaFunction* func);
+ void collectInstantiatedContainersAndSmartPointers(const AbstractMetaClass *metaClass);
+ void collectInstantiatedContainersAndSmartPointers();
};
Q_DECLARE_OPERATORS_FOR_FLAGS(Generator::Options)
diff --git a/generator/qtdoc/qtdocgenerator.cpp b/generator/qtdoc/qtdocgenerator.cpp
index 3e6f113..a7a1769 100644
--- a/generator/qtdoc/qtdocgenerator.cpp
+++ b/generator/qtdoc/qtdocgenerator.cpp
@@ -990,9 +990,21 @@ QtDocGenerator::~QtDocGenerator()
delete m_docParser;
}
-QString QtDocGenerator::fileNameForClass(const AbstractMetaClass* cppClass) const
+QString QtDocGenerator::fileNamePrefix() const
{
- return getClassTargetFullName(cppClass, false) + QLatin1String(".rst");
+ return QLatin1String(".rst");
+}
+
+QString QtDocGenerator::fileNameForContext(GeneratorContext &context) const
+{
+ const AbstractMetaClass *metaClass = context.metaClass();
+ if (!context.forSmartPointer()) {
+ return getClassTargetFullName(metaClass, false) + fileNamePrefix();
+ } else {
+ const AbstractMetaType *smartPointerType = context.preciseType();
+ QString fileNameBase = getFileNameBaseForSmartPointer(smartPointerType, metaClass);
+ return fileNameBase + fileNamePrefix();
+ }
}
void QtDocGenerator::writeFormatedText(QTextStream& s, const Documentation& doc, const AbstractMetaClass* metaClass)
@@ -1040,11 +1052,12 @@ static void writeInheritedByList(QTextStream& s, const AbstractMetaClass* metaCl
s << classes.join(QLatin1String(", ")) << endl << endl;
}
-void QtDocGenerator::generateClass(QTextStream& s, const AbstractMetaClass* metaClass)
+void QtDocGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
{
+ AbstractMetaClass *metaClass = classContext.metaClass();
qCDebug(lcShiboken).noquote().nospace() << "Generating Documentation for " << metaClass->fullName();
- m_packages[metaClass->package()] << fileNameForClass(metaClass);
+ m_packages[metaClass->package()] << fileNameForContext(classContext);
m_docParser->setPackageName(metaClass->package());
m_docParser->fillDocumentation(const_cast<AbstractMetaClass*>(metaClass));
diff --git a/generator/qtdoc/qtdocgenerator.h b/generator/qtdoc/qtdocgenerator.h
index ec815ad..fa8524b 100644
--- a/generator/qtdoc/qtdocgenerator.h
+++ b/generator/qtdoc/qtdocgenerator.h
@@ -194,8 +194,9 @@ public:
}
protected:
- QString fileNameForClass(const AbstractMetaClass* cppClass) const;
- void generateClass(QTextStream& s, const AbstractMetaClass* metaClass);
+ QString fileNamePrefix() const;
+ QString fileNameForContext(GeneratorContext &context) const;
+ void generateClass(QTextStream &s, GeneratorContext &classContext);
bool finishGeneration();
void writeFunctionArguments(QTextStream&, const AbstractMetaFunction*, Options) const {}
diff --git a/generator/shiboken2/cppgenerator.cpp b/generator/shiboken2/cppgenerator.cpp
index 7ff280a..c8e919c 100644
--- a/generator/shiboken2/cppgenerator.cpp
+++ b/generator/shiboken2/cppgenerator.cpp
@@ -134,11 +134,23 @@ CppGenerator::CppGenerator()
m_mpFuncs.insert(QLatin1String("__msetitem__"), QLatin1String("mp_ass_subscript"));
}
-QString CppGenerator::fileNameForClass(const AbstractMetaClass *metaClass) const
+QString CppGenerator::fileNamePrefix() const
{
- QString result = metaClass->qualifiedCppName().toLower();
- result.replace(QLatin1String("::"), QLatin1String("_"));
- return result + QLatin1String("_wrapper.cpp");
+ return QLatin1String("_wrapper.cpp");
+}
+
+QString CppGenerator::fileNameForContext(GeneratorContext &context) const
+{
+ const AbstractMetaClass *metaClass = context.metaClass();
+ if (!context.forSmartPointer()) {
+ QString fileNameBase = metaClass->qualifiedCppName().toLower();
+ fileNameBase.replace(QLatin1String("::"), QLatin1String("_"));
+ return fileNameBase + fileNamePrefix();
+ } else {
+ const AbstractMetaType *smartPointerType = context.preciseType();
+ QString fileNameBase = getFileNameBaseForSmartPointer(smartPointerType, metaClass);
+ return fileNameBase + fileNamePrefix();
+ }
}
QList<AbstractMetaFunctionList> CppGenerator::filterGroupedOperatorFunctions(const AbstractMetaClass* metaClass,
@@ -148,8 +160,11 @@ QList<AbstractMetaFunctionList> CppGenerator::filterGroupedOperatorFunctions(con
QMap<QPair<QString, int >, AbstractMetaFunctionList> results;
const AbstractMetaClass::OperatorQueryOptions query(queryIn);
foreach (AbstractMetaFunction* func, metaClass->operatorOverloads(query)) {
- if (func->isModifiedRemoved() || func->usesRValueReferences()
- || func->name() == QLatin1String("operator[]") || func->name() == QLatin1String("operator->")) {
+ if (func->isModifiedRemoved()
+ || func->usesRValueReferences()
+ || func->name() == QLatin1String("operator[]")
+ || func->name() == QLatin1String("operator->")
+ || func->name() == QLatin1String("operator!")) {
continue;
}
int args;
@@ -193,8 +208,9 @@ static const char includeQDebug[] =
\param s the output buffer
\param metaClass the pointer to metaclass information
*/
-void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaClass)
+void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
{
+ AbstractMetaClass *metaClass = classContext.metaClass();
if (ReportHandler::isDebug(ReportHandler::SparseDebug))
qCDebug(lcShiboken) << "Generating wrapper implementation for " << metaClass->fullName();
@@ -231,12 +247,13 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl
s << "#include \"" << getModuleHeaderFileName() << '"' << endl << endl;
- QString headerfile = fileNameForClass(metaClass);
+ QString headerfile = fileNameForContext(classContext);
headerfile.replace(QLatin1String(".cpp"), QLatin1String(".h"));
s << "#include \"" << headerfile << '"' << endl;
foreach (AbstractMetaClass* innerClass, metaClass->innerClasses()) {
+ GeneratorContext innerClassContext(innerClass);
if (shouldGenerate(innerClass)) {
- QString headerfile = fileNameForClass(innerClass);
+ QString headerfile = fileNameForContext(innerClassContext);
headerfile.replace(QLatin1String(".cpp"), QLatin1String(".h"));
s << "#include \"" << headerfile << '"' << endl;
}
@@ -259,18 +276,29 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl
if (metaClass->typeEntry()->typeFlags() & ComplexTypeEntry::Deprecated)
s << "#Deprecated" << endl;
- //Use class base namespace
- const AbstractMetaClass *context = metaClass->enclosingClass();
- while(context) {
- if (context->isNamespace() && !context->enclosingClass()) {
- s << "using namespace " << context->qualifiedCppName() << ";" << endl;
- break;
+ // Use class base namespace
+ {
+ const AbstractMetaClass *context = metaClass->enclosingClass();
+ while (context) {
+ if (context->isNamespace() && !context->enclosingClass()) {
+ s << "using namespace " << context->qualifiedCppName() << ";" << endl;
+ break;
+ }
+ context = context->enclosingClass();
}
- context = context->enclosingClass();
}
s << endl;
+ // Create string literal for smart pointer getter method.
+ if (classContext.forSmartPointer()) {
+ const SmartPointerTypeEntry *typeEntry =
+ static_cast<const SmartPointerTypeEntry *>(classContext.preciseType()
+ ->typeEntry());
+ QString rawGetter = typeEntry->getter();
+ s << "static const char * " SMART_POINTER_GETTER " = \"" << rawGetter << "\";";
+ }
+
// class inject-code native/beginning
if (!metaClass->typeEntry()->codeSnips().isEmpty()) {
writeCodeSnips(s, metaClass->typeEntry()->codeSnips(), TypeSystem::CodeSnipPositionBeginning, TypeSystem::NativeCode, metaClass);
@@ -290,7 +318,7 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl
if (avoidProtectedHack() && usePySideExtensions()) {
s << "void " << wrapperName(metaClass) << "::pysideInitQtMetaTypes()\n{\n";
Indentation indent(INDENT);
- writeInitQtMetaTypeFunctionBody(s, metaClass);
+ writeInitQtMetaTypeFunctionBody(s, classContext);
s << "}\n\n";
}
@@ -342,13 +370,46 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl
if (m_sequenceProtocol.contains(rfunc->name()) || m_mappingProtocol.contains(rfunc->name()))
continue;
- if (rfunc->isConstructor())
- writeConstructorWrapper(s, overloads);
+ if (rfunc->isConstructor()) {
+ // @TODO: Implement constructor support for smart pointers, so that they can be
+ // instantiated in python code.
+ if (classContext.forSmartPointer())
+ continue;
+ writeConstructorWrapper(s, overloads, classContext);
+ }
// call operators
else if (rfunc->name() == QLatin1String("operator()"))
- writeMethodWrapper(s, overloads);
+ writeMethodWrapper(s, overloads, classContext);
else if (!rfunc->isOperatorOverload()) {
- writeMethodWrapper(s, overloads);
+
+ if (classContext.forSmartPointer()) {
+ const SmartPointerTypeEntry *smartPointerTypeEntry =
+ static_cast<const SmartPointerTypeEntry *>(
+ classContext.preciseType()->typeEntry());
+
+ if (smartPointerTypeEntry->getter() == rfunc->name()) {
+ // Replace the return type of the raw pointer getter method with the actual
+ // return type.
+ QString innerTypeName =
+ classContext.preciseType()->getSmartPointerInnerType()->name();
+ QString pointerToInnerTypeName = innerTypeName + QLatin1Char('*');
+ // @TODO: This possibly leaks, but there are a bunch of other places where this
+ // is done, so this will be fixed in bulk with all the other cases, because the
+ // ownership of the pointers is not clear at the moment.
+ AbstractMetaType *pointerToInnerType =
+ buildAbstractMetaTypeFromString(pointerToInnerTypeName);
+
+ AbstractMetaFunction *mutableRfunc = overloads.first();
+ mutableRfunc->replaceType(pointerToInnerType);
+ } else if (smartPointerTypeEntry->refCountMethodName().isEmpty()
+ || smartPointerTypeEntry->refCountMethodName() != rfunc->name()) {
+ // Skip all public methods of the smart pointer except for the raw getter and
+ // the ref count method.
+ continue;
+ }
+ }
+
+ writeMethodWrapper(s, overloads, classContext);
if (OverloadData::hasStaticAndInstanceFunctions(overloads)) {
QString methDefName = cpythonMethodDefinitionName(rfunc);
smd << "static PyMethodDef " << methDefName << " = {" << endl;
@@ -363,8 +424,8 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl
QString className = cpythonTypeName(metaClass);
className.remove(QRegExp(QLatin1String("_Type$")));
- if (metaClass->typeEntry()->isValue())
- writeCopyFunction(s, metaClass);
+ if (metaClass->typeEntry()->isValue() || metaClass->typeEntry()->isSmartPointer())
+ writeCopyFunction(s, classContext);
// Write single method definitions
s << singleMethodDefinitions;
@@ -372,27 +433,33 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl
// Write methods definition
s << "static PyMethodDef " << className << "_methods[] = {" << endl;
s << methodsDefinitions << endl;
- if (metaClass->typeEntry()->isValue())
+ if (metaClass->typeEntry()->isValue() || metaClass->typeEntry()->isSmartPointer())
s << INDENT << "{\"__copy__\", (PyCFunction)" << className << "___copy__" << ", METH_NOARGS}," << endl;
s << INDENT << "{0} // Sentinel" << endl;
s << "};" << endl << endl;
// Write tp_getattro function
- if (usePySideExtensions() && metaClass->qualifiedCppName() == QLatin1String("QObject")) {
- writeGetattroFunction(s, metaClass);
+ if ((usePySideExtensions() && metaClass->qualifiedCppName() == QLatin1String("QObject"))) {
+ writeGetattroFunction(s, classContext);
s << endl;
- writeSetattroFunction(s, metaClass);
- s << endl;
- } else if (classNeedsGetattroFunction(metaClass)) {
- writeGetattroFunction(s, metaClass);
+ writeSetattroFunction(s, classContext);
s << endl;
+ } else {
+ if (classNeedsGetattroFunction(metaClass)) {
+ writeGetattroFunction(s, classContext);
+ s << endl;
+ }
+ if (classNeedsSetattroFunction(metaClass)) {
+ writeSetattroFunction(s, classContext);
+ s << endl;
+ }
}
if (hasBoolCast(metaClass)) {
ErrorCode errorCode(-1);
s << "static int " << cpythonBaseName(metaClass) << "___nb_bool(PyObject* " PYTHON_SELF_VAR ")" << endl;
s << '{' << endl;
- writeCppSelfDefinition(s, metaClass);
+ writeCppSelfDefinition(s, classContext);
s << INDENT << "int result;" << endl;
s << INDENT << BEGIN_ALLOW_THREADS << endl;
s << INDENT << "result = !" CPP_SELF_VAR "->isNull();" << endl;
@@ -401,7 +468,7 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl
s << '}' << endl << endl;
}
- if (supportsNumberProtocol(metaClass)) {
+ if (supportsNumberProtocol(metaClass) && !metaClass->typeEntry()->isSmartPointer()) {
QList<AbstractMetaFunctionList> opOverloads = filterGroupedOperatorFunctions(
metaClass,
AbstractMetaClass::ArithmeticOp
@@ -420,30 +487,30 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl
if (overloads.isEmpty())
continue;
- writeMethodWrapper(s, overloads);
+ writeMethodWrapper(s, overloads, classContext);
}
}
if (supportsSequenceProtocol(metaClass)) {
- writeSequenceMethods(s, metaClass);
+ writeSequenceMethods(s, metaClass, classContext);
}
if (supportsMappingProtocol(metaClass)) {
- writeMappingMethods(s, metaClass);
+ writeMappingMethods(s, metaClass, classContext);
}
if (metaClass->hasComparisonOperatorOverload()) {
s << "// Rich comparison" << endl;
- writeRichCompareFunction(s, metaClass);
+ writeRichCompareFunction(s, classContext);
}
- if (shouldGenerateGetSetList(metaClass)) {
+ if (shouldGenerateGetSetList(metaClass) && !classContext.forSmartPointer()) {
foreach (const AbstractMetaField* metaField, metaClass->fields()) {
if (metaField->isStatic())
continue;
- writeGetterFunction(s, metaField);
+ writeGetterFunction(s, metaField, classContext);
if (!metaField->type()->isConstant())
- writeSetterFunction(s, metaField);
+ writeSetterFunction(s, metaField, classContext);
s << endl;
}
@@ -466,13 +533,13 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl
s << "} // extern \"C\"" << endl << endl;
if (!metaClass->typeEntry()->hashFunction().isEmpty())
- writeHashFunction(s, metaClass);
+ writeHashFunction(s, classContext);
// Write tp_traverse and tp_clear functions.
writeTpTraverseFunction(s, metaClass);
writeTpClearFunction(s, metaClass);
- writeClassDefinition(s, metaClass);
+ writeClassDefinition(s, metaClass, classContext);
s << endl;
if (metaClass->isPolymorphic() && metaClass->baseClass())
@@ -492,8 +559,8 @@ void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *metaCl
}
s << endl;
- writeConverterFunctions(s, metaClass);
- writeClassRegister(s, metaClass);
+ writeConverterFunctions(s, metaClass, classContext);
+ writeClassRegister(s, metaClass, classContext);
// class inject-code native/end
if (!metaClass->typeEntry()->codeSnips().isEmpty()) {
@@ -997,7 +1064,8 @@ void CppGenerator::writeEnumConverterFunctions(QTextStream& s, const TypeEntry*
QLatin1String("PyNumber_Check(pyIn)"));
}
-void CppGenerator::writeConverterFunctions(QTextStream& s, const AbstractMetaClass* metaClass)
+void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaClass *metaClass,
+ GeneratorContext &classContext)
{
s << "// Type conversion functions." << endl << endl;
@@ -1012,7 +1080,12 @@ void CppGenerator::writeConverterFunctions(QTextStream& s, const AbstractMetaCla
if (metaClass->isNamespace())
return;
- QString typeName = getFullTypeName(metaClass);
+ QString typeName;
+ if (!classContext.forSmartPointer())
+ typeName = getFullTypeName(metaClass);
+ else
+ typeName = getFullTypeName(classContext.preciseType());
+
QString cpythonType = cpythonTypeName(metaClass);
// Returns the C++ pointer of the Python wrapper.
@@ -1053,29 +1126,52 @@ void CppGenerator::writeConverterFunctions(QTextStream& s, const AbstractMetaCla
writeCppToPythonFunction(s, code, sourceTypeName, targetTypeName);
// The conversions for an Object Type end here.
- if (!metaClass->typeEntry()->isValue()) {
+ if (!metaClass->typeEntry()->isValue() && !metaClass->typeEntry()->isSmartPointer()) {
s << endl;
return;
}
// Always copies C++ value (not pointer, and not reference) to a new Python wrapper.
s << endl << "// C++ to Python copy conversion." << endl;
- targetTypeName = metaClass->name();
+ if (!classContext.forSmartPointer())
+ targetTypeName = metaClass->name();
+ else
+ targetTypeName = classContext.preciseType()->name();
+
sourceTypeName = targetTypeName + QLatin1String("_COPY");
code.clear();
- c << INDENT << "return Shiboken::Object::newObject(&" << cpythonType << ", new ::" << wrapperName(metaClass);
+
+ QString computedWrapperName;
+ if (!classContext.forSmartPointer())
+ computedWrapperName = wrapperName(metaClass);
+ else
+ computedWrapperName = wrapperName(classContext.preciseType());
+
+ c << INDENT << "return Shiboken::Object::newObject(&" << cpythonType << ", new ::" << computedWrapperName;
c << "(*((" << typeName << "*)cppIn)), true, true);";
writeCppToPythonFunction(s, code, sourceTypeName, targetTypeName);
s << endl;
// Python to C++ copy conversion.
s << "// Python to C++ copy conversion." << endl;
- sourceTypeName = metaClass->name();
+ if (!classContext.forSmartPointer())
+ sourceTypeName = metaClass->name();
+ else
+ sourceTypeName = classContext.preciseType()->name();
+
targetTypeName = QStringLiteral("%1_COPY").arg(sourceTypeName);
code.clear();
+
+ QString pyInVariable = QLatin1String("pyIn");
+ QString wrappedCPtrExpression;
+ if (!classContext.forSmartPointer())
+ wrappedCPtrExpression = cpythonWrapperCPtr(metaClass->typeEntry(), pyInVariable);
+ else
+ wrappedCPtrExpression = cpythonWrapperCPtr(classContext.preciseType(), pyInVariable);
+
c << INDENT << "*((" << typeName << "*)cppOut) = *"
- << cpythonWrapperCPtr(metaClass->typeEntry(), QLatin1String("pyIn")) << ';';
+ << wrappedCPtrExpression << ';';
writePythonToCppFunction(s, code, sourceTypeName, targetTypeName);
// "Is convertible" function for the Python object to C++ value copy conversion.
@@ -1177,7 +1273,8 @@ void CppGenerator::writeCustomConverterFunctions(QTextStream& s, const CustomCon
s << endl;
}
-void CppGenerator::writeConverterRegister(QTextStream& s, const AbstractMetaClass* metaClass)
+void CppGenerator::writeConverterRegister(QTextStream &s, const AbstractMetaClass *metaClass,
+ GeneratorContext &classContext)
{
if (metaClass->isNamespace())
return;
@@ -1192,7 +1289,7 @@ void CppGenerator::writeConverterRegister(QTextStream& s, const AbstractMetaClas
s << INDENT << convertibleToCppFunctionName(sourceTypeName, targetTypeName) << ',' << endl;
std::swap(targetTypeName, sourceTypeName);
s << INDENT << cppToPythonFunctionName(sourceTypeName, targetTypeName);
- if (metaClass->typeEntry()->isValue()) {
+ if (metaClass->typeEntry()->isValue() || metaClass->typeEntry()->isSmartPointer()) {
s << ',' << endl;
sourceTypeName = metaClass->name() + QLatin1String("_COPY");
s << INDENT << cppToPythonFunctionName(sourceTypeName, targetTypeName);
@@ -1202,7 +1299,14 @@ void CppGenerator::writeConverterRegister(QTextStream& s, const AbstractMetaClas
s << endl;
- QStringList cppSignature = metaClass->qualifiedCppName().split(QLatin1String("::"), QString::SkipEmptyParts);
+ QStringList cppSignature;
+ if (!classContext.forSmartPointer()) {
+ cppSignature = metaClass->qualifiedCppName().split(QLatin1String("::"),
+ QString::SkipEmptyParts);
+ } else {
+ cppSignature = classContext.preciseType()->cppSignature().split(QLatin1String("::"),
+ QString::SkipEmptyParts);
+ }
while (!cppSignature.isEmpty()) {
QString signature = cppSignature.join(QLatin1String("::"));
s << INDENT << "Shiboken::Conversions::registerConverterName(converter, \"" << signature << "\");" << endl;
@@ -1212,7 +1316,14 @@ void CppGenerator::writeConverterRegister(QTextStream& s, const AbstractMetaClas
}
s << INDENT << "Shiboken::Conversions::registerConverterName(converter, typeid(::";
- s << metaClass->qualifiedCppName() << ").name());" << endl;
+ QString qualifiedCppNameInvocation;
+ if (!classContext.forSmartPointer())
+ qualifiedCppNameInvocation = metaClass->qualifiedCppName();
+ else
+ qualifiedCppNameInvocation = classContext.preciseType()->cppSignature();
+
+ s << qualifiedCppNameInvocation << ").name());" << endl;
+
if (shouldGenerateCppWrapper(metaClass)) {
s << INDENT << "Shiboken::Conversions::registerConverterName(converter, typeid(::";
s << wrapperName(metaClass) << ").name());" << endl;
@@ -1220,7 +1331,7 @@ void CppGenerator::writeConverterRegister(QTextStream& s, const AbstractMetaClas
s << endl;
- if (!metaClass->typeEntry()->isValue())
+ if (!metaClass->typeEntry()->isValue() && !metaClass->typeEntry()->isSmartPointer())
return;
// Python to C++ copy (value, not pointer neither reference) conversion.
@@ -1297,7 +1408,8 @@ void CppGenerator::writeContainerConverterFunctions(QTextStream& s, const Abstra
writePythonToCppConversionFunctions(s, containerType);
}
-void CppGenerator::writeMethodWrapperPreamble(QTextStream& s, OverloadData& overloadData)
+void CppGenerator::writeMethodWrapperPreamble(QTextStream &s, OverloadData &overloadData,
+ GeneratorContext &context)
{
const AbstractMetaFunction* rfunc = overloadData.referenceFunction();
const AbstractMetaClass* ownerClass = rfunc->ownerClass();
@@ -1312,13 +1424,24 @@ void CppGenerator::writeMethodWrapperPreamble(QTextStream& s, OverloadData& over
if (!ownerClass->hasPrivateDestructor()) {
s << INDENT;
s << "if (Shiboken::Object::isUserType(" PYTHON_SELF_VAR ") && !Shiboken::ObjectType::canCallConstructor(" PYTHON_SELF_VAR "->ob_type, Shiboken::SbkType< ::";
- s << ownerClass->qualifiedCppName() << " >()))" << endl;
+ QString qualifiedCppName;
+ if (!context.forSmartPointer())
+ qualifiedCppName = ownerClass->qualifiedCppName();
+ else
+ qualifiedCppName = context.preciseType()->cppSignature();
+
+ s << qualifiedCppName << " >()))" << endl;
Indentation indent(INDENT);
s << INDENT << "return " << m_currentErrorCode << ';' << endl << endl;
}
// Declare pointer for the underlying C++ object.
s << INDENT << "::";
- s << (shouldGenerateCppWrapper(ownerClass) ? wrapperName(ownerClass) : ownerClass->qualifiedCppName());
+ if (!context.forSmartPointer()) {
+ s << (shouldGenerateCppWrapper(ownerClass) ? wrapperName(ownerClass)
+ : ownerClass->qualifiedCppName());
+ } else {
+ s << context.preciseType()->cppSignature();
+ }
s << "* cptr = 0;" << endl;
initPythonArguments = maxArgs > 0;
@@ -1327,7 +1450,7 @@ void CppGenerator::writeMethodWrapperPreamble(QTextStream& s, OverloadData& over
} else {
if (rfunc->implementingClass() &&
(!rfunc->implementingClass()->isNamespace() && overloadData.hasInstanceFunction())) {
- writeCppSelfDefinition(s, rfunc, overloadData.hasStaticFunction());
+ writeCppSelfDefinition(s, rfunc, context, overloadData.hasStaticFunction());
}
if (!rfunc->isInplaceOperator() && overloadData.hasNonVoidReturnType())
s << INDENT << "PyObject* " PYTHON_RETURN_VAR " = 0;" << endl;
@@ -1357,7 +1480,8 @@ void CppGenerator::writeMethodWrapperPreamble(QTextStream& s, OverloadData& over
}
}
-void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFunctionList overloads)
+void CppGenerator::writeConstructorWrapper(QTextStream &s, const AbstractMetaFunctionList overloads,
+ GeneratorContext &classContext)
{
ErrorCode errorCode(-1);
OverloadData overloadData(overloads, this);
@@ -1424,14 +1548,14 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun
s << INDENT << '}' << endl << endl;
}
- writeMethodWrapperPreamble(s, overloadData);
+ writeMethodWrapperPreamble(s, overloadData, classContext);
s << endl;
if (overloadData.maxArgs() > 0)
writeOverloadedFunctionDecisor(s, overloadData);
- writeFunctionCalls(s, overloadData);
+ writeFunctionCalls(s, overloadData, classContext);
s << endl;
s << INDENT << "if (PyErr_Occurred() || !Shiboken::Object::setCppPointer(sbkSelf, Shiboken::SbkType< ::" << metaClass->qualifiedCppName() << " >(), cptr)) {" << endl;
@@ -1505,7 +1629,8 @@ void CppGenerator::writeConstructorWrapper(QTextStream& s, const AbstractMetaFun
s << '}' << endl << endl;
}
-void CppGenerator::writeMethodWrapper(QTextStream& s, const AbstractMetaFunctionList overloads)
+void CppGenerator::writeMethodWrapper(QTextStream &s, const AbstractMetaFunctionList overloads,
+ GeneratorContext &classContext)
{
OverloadData overloadData(overloads, this);
const AbstractMetaFunction* rfunc = overloadData.referenceFunction();
@@ -1521,7 +1646,7 @@ void CppGenerator::writeMethodWrapper(QTextStream& s, const AbstractMetaFunction
}
s << ')' << endl << '{' << endl;
- writeMethodWrapperPreamble(s, overloadData);
+ writeMethodWrapperPreamble(s, overloadData, classContext);
s << endl;
@@ -1579,7 +1704,7 @@ void CppGenerator::writeMethodWrapper(QTextStream& s, const AbstractMetaFunction
if (maxArgs > 0)
writeOverloadedFunctionDecisor(s, overloadData);
- writeFunctionCalls(s, overloadData);
+ writeFunctionCalls(s, overloadData, classContext);
if (callExtendedReverseOperator)
s << endl << INDENT << "} // End of \"if (!" PYTHON_RETURN_VAR ")\"" << endl;
@@ -1697,26 +1822,42 @@ void CppGenerator::writeArgumentsInitializer(QTextStream& s, OverloadData& overl
s << endl;
}
-void CppGenerator::writeCppSelfDefinition(QTextStream& s, const AbstractMetaClass* metaClass, bool hasStaticOverload, bool cppSelfAsReference)
+void CppGenerator::writeCppSelfDefinition(QTextStream &s,
+ GeneratorContext &context,
+ bool hasStaticOverload,
+ bool cppSelfAsReference)
{
+ const AbstractMetaClass *metaClass = context.metaClass();
bool useWrapperClass = avoidProtectedHack() && metaClass->hasProtectedMembers();
- QString className = useWrapperClass
- ? wrapperName(metaClass)
- : (QLatin1String("::") + metaClass->qualifiedCppName());
+ QString className;
+ if (!context.forSmartPointer()) {
+ className = useWrapperClass
+ ? wrapperName(metaClass)
+ : (QLatin1String("::") + metaClass->qualifiedCppName());
+ } else {
+ className = context.preciseType()->cppSignature();
+ }
QString cppSelfAttribution;
+ QString pythonSelfVar = QLatin1String(PYTHON_SELF_VAR);
+ QString cpythonWrapperCPtrResult;
+ if (!context.forSmartPointer())
+ cpythonWrapperCPtrResult = cpythonWrapperCPtr(metaClass, pythonSelfVar);
+ else
+ cpythonWrapperCPtrResult = cpythonWrapperCPtr(context.preciseType(), pythonSelfVar);
+
if (cppSelfAsReference) {
QString cast = useWrapperClass ? QString::fromLatin1("(%1*)").arg(className) : QString();
cppSelfAttribution = QString::fromLatin1("%1& %2 = *(%3%4)")
.arg(className, QLatin1String(CPP_SELF_VAR), cast,
- cpythonWrapperCPtr(metaClass, QLatin1String(PYTHON_SELF_VAR)));
+ cpythonWrapperCPtrResult);
} else {
s << INDENT << className << "* " CPP_SELF_VAR " = 0;" << endl;
writeUnusedVariableCast(s, QLatin1String(CPP_SELF_VAR));
cppSelfAttribution = QString::fromLatin1("%1 = %2%3")
.arg(QLatin1String(CPP_SELF_VAR),
(useWrapperClass ? QString::fromLatin1("(%1*)").arg(className) : QString()),
- cpythonWrapperCPtr(metaClass, QLatin1String(PYTHON_SELF_VAR)));
+ cpythonWrapperCPtrResult);
}
// Checks if the underlying C++ object is valid.
@@ -1735,7 +1876,10 @@ void CppGenerator::writeCppSelfDefinition(QTextStream& s, const AbstractMetaClas
s << INDENT << cppSelfAttribution << ';' << endl;
}
-void CppGenerator::writeCppSelfDefinition(QTextStream& s, const AbstractMetaFunction* func, bool hasStaticOverload)
+void CppGenerator::writeCppSelfDefinition(QTextStream &s,
+ const AbstractMetaFunction *func,
+ GeneratorContext &context,
+ bool hasStaticOverload)
{
if (!func->ownerClass() || func->isConstructor())
return;
@@ -1755,7 +1899,7 @@ void CppGenerator::writeCppSelfDefinition(QTextStream& s, const AbstractMetaFunc
s << INDENT << "std::swap(" PYTHON_SELF_VAR ", " PYTHON_ARG ");" << endl;
}
- writeCppSelfDefinition(s, func->ownerClass(), hasStaticOverload);
+ writeCppSelfDefinition(s, context, hasStaticOverload);
}
void CppGenerator::writeErrorSection(QTextStream& s, OverloadData& overloadData)
@@ -2056,7 +2200,7 @@ void CppGenerator::writePythonToCppTypeConversion(QTextStream& s,
s << "(long)" << defaultValue;
} else if (isUserPrimitive(type) || typeEntry->isEnum() || typeEntry->isFlags()) {
writeMinimalConstructorExpression(s, typeEntry, defaultValue);
- } else if (!type->isContainer()) {
+ } else if (!type->isContainer() && !type->isSmartPointer()) {
writeMinimalConstructorExpression(s, type, defaultValue);
}
}
@@ -2326,7 +2470,8 @@ void CppGenerator::writeOverloadedFunctionDecisorEngine(QTextStream& s, const Ov
s << endl;
}
-void CppGenerator::writeFunctionCalls(QTextStream& s, const OverloadData& overloadData)
+void CppGenerator::writeFunctionCalls(QTextStream &s, const OverloadData &overloadData,
+ GeneratorContext &context)
{
QList<const AbstractMetaFunction*> overloads = overloadData.overloadsWithoutRepetition();
s << INDENT << "// Call function/method" << endl;
@@ -2334,7 +2479,7 @@ void CppGenerator::writeFunctionCalls(QTextStream& s, const OverloadData& overlo
{
Indentation indent(INDENT);
if (overloads.count() == 1) {
- writeSingleFunctionCall(s, overloadData, overloads.first());
+ writeSingleFunctionCall(s, overloadData, overloads.first(), context);
} else {
for (int i = 0; i < overloads.count(); i++) {
const AbstractMetaFunction* func = overloads.at(i);
@@ -2342,7 +2487,7 @@ void CppGenerator::writeFunctionCalls(QTextStream& s, const OverloadData& overlo
s << INDENT << '{' << endl;
{
Indentation indent(INDENT);
- writeSingleFunctionCall(s, overloadData, func);
+ writeSingleFunctionCall(s, overloadData, func, context);
s << INDENT << "break;" << endl;
}
s << INDENT << '}' << endl;
@@ -2352,7 +2497,10 @@ void CppGenerator::writeFunctionCalls(QTextStream& s, const OverloadData& overlo
s << INDENT << '}' << endl;
}
-void CppGenerator::writeSingleFunctionCall(QTextStream& s, const OverloadData& overloadData, const AbstractMetaFunction* func)
+void CppGenerator::writeSingleFunctionCall(QTextStream &s,
+ const OverloadData &overloadData,
+ const AbstractMetaFunction *func,
+ GeneratorContext &context)
{
if (func->isDeprecated()) {
s << INDENT << "Shiboken::warning(PyExc_DeprecationWarning, 1, \"Function: '"
@@ -2413,7 +2561,7 @@ void CppGenerator::writeSingleFunctionCall(QTextStream& s, const OverloadData& o
s << INDENT << "if (!PyErr_Occurred()) {" << endl;
{
Indentation indentation(INDENT);
- writeMethodCall(s, func, func->arguments().size() - numRemovedArgs);
+ writeMethodCall(s, func, context, func->arguments().size() - numRemovedArgs);
if (!func->isConstructor())
writeNoneReturn(s, func, overloadData.hasNonVoidReturnType());
}
@@ -2772,7 +2920,8 @@ QString CppGenerator::argumentNameFromIndex(const AbstractMetaFunction* func, in
return pyArgName;
}
-void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* func, int maxArgs)
+void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *func,
+ GeneratorContext &context, int maxArgs)
{
s << INDENT << "// " << func->minimalSignature() << (func->isReverseOperator() ? " [reverse operator]": "") << endl;
if (func->isConstructor()) {
@@ -2946,10 +3095,16 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f
}
}
} else {
+ QString methodCallClassName;
+ if (context.forSmartPointer())
+ methodCallClassName = context.preciseType()->cppSignature();
+ else if (func->ownerClass())
+ methodCallClassName = func->ownerClass()->qualifiedCppName();
+
if (func->ownerClass()) {
if (!avoidProtectedHack() || !func->isProtected()) {
if (func->isStatic()) {
- mc << "::" << func->ownerClass()->qualifiedCppName() << "::";
+ mc << "::" << methodCallClassName << "::";
} else {
if (func->isConstant()) {
if (avoidProtectedHack()) {
@@ -2957,10 +3112,10 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f
if (func->ownerClass()->hasProtectedMembers())
mc << wrapperName(func->ownerClass());
else
- mc << func->ownerClass()->qualifiedCppName();
+ mc << methodCallClassName;
mc << "*>(" CPP_SELF_VAR ")->";
} else {
- mc << "const_cast<const ::" << func->ownerClass()->qualifiedCppName();
+ mc << "const_cast<const ::" << methodCallClassName;
mc << "*>(" CPP_SELF_VAR ")->";
}
} else {
@@ -2977,7 +3132,9 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f
mc << "((::" << wrapperName(func->ownerClass()) << "*) " << CPP_SELF_VAR << ")->";
if (!func->isAbstract())
- mc << (func->isProtected() ? wrapperName(func->ownerClass()) : QLatin1String("::") + func->ownerClass()->qualifiedCppName()) << "::";
+ mc << (func->isProtected() ? wrapperName(func->ownerClass()) :
+ QLatin1String("::")
+ + methodCallClassName) << "::";
mc << func->originalName() << "_protected";
}
} else {
@@ -2989,7 +3146,8 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f
if (!avoidProtectedHack() || !func->isProtected()) {
QString virtualCall(methodCall);
QString normalCall(methodCall);
- virtualCall = virtualCall.replace(QLatin1String("%CLASS_NAME"), func->ownerClass()->qualifiedCppName());
+ virtualCall = virtualCall.replace(QLatin1String("%CLASS_NAME"),
+ methodCallClassName);
normalCall.remove(QLatin1String("::%CLASS_NAME::"));
methodCall.clear();
mc << "Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject*>(" PYTHON_SELF_VAR ")) ? ";
@@ -3398,7 +3556,9 @@ bool CppGenerator::shouldGenerateGetSetList(const AbstractMetaClass* metaClass)
return false;
}
-void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass* metaClass)
+void CppGenerator::writeClassDefinition(QTextStream &s,
+ const AbstractMetaClass *metaClass,
+ GeneratorContext &classContext)
{
QString tp_flags;
QString tp_init;
@@ -3412,7 +3572,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass*
QString baseClassName(QLatin1Char('0'));
AbstractMetaFunctionList ctors;
foreach (AbstractMetaFunction* f, metaClass->queryFunctions(AbstractMetaClass::Constructors)) {
- if (!f->isPrivate() && !f->isModifiedRemoved())
+ if (!f->isPrivate() && !f->isModifiedRemoved() && !classContext.forSmartPointer())
ctors.append(f);
}
@@ -3447,8 +3607,11 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass*
if (usePySideExtensions() && (metaClass->qualifiedCppName() == QLatin1String("QObject"))) {
tp_getattro = cpythonGetattroFunctionName(metaClass);
tp_setattro = cpythonSetattroFunctionName(metaClass);
- } else if (classNeedsGetattroFunction(metaClass)) {
- tp_getattro = cpythonGetattroFunctionName(metaClass);
+ } else {
+ if (classNeedsGetattroFunction(metaClass))
+ tp_getattro = cpythonGetattroFunctionName(metaClass);
+ if (classNeedsSetattroFunction(metaClass))
+ tp_setattro = cpythonSetattroFunctionName(metaClass);
}
if (metaClass->hasPrivateDestructor() || onlyPrivCtor)
@@ -3461,7 +3624,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass*
tp_richcompare = cpythonBaseName(metaClass) + QLatin1String("_richcompare");
QString tp_getset = QString(QLatin1Char('0'));
- if (shouldGenerateGetSetList(metaClass))
+ if (shouldGenerateGetSetList(metaClass) && !classContext.forSmartPointer())
tp_getset = cpythonGettersSettersDefinitionName(metaClass);
// search for special functions
@@ -3473,7 +3636,7 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass*
if (m_tpFuncs[QLatin1String("__repr__")] == QLatin1String("0")
&& !metaClass->isQObject()
&& metaClass->hasToStringCapability()) {
- m_tpFuncs[QLatin1String("__repr__")] = writeReprFunction(s, metaClass);
+ m_tpFuncs[QLatin1String("__repr__")] = writeReprFunction(s, classContext);
}
// class or some ancestor has multiple inheritance
@@ -3512,7 +3675,13 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass*
s << "static SbkObjectType " << className + QLatin1String("_Type") << " = { { {" << endl;
s << INDENT << "PyVarObject_HEAD_INIT(&SbkObjectType_Type, 0)" << endl;
- s << INDENT << "/*tp_name*/ \"" << getClassTargetFullName(metaClass) << "\"," << endl;
+ QString computedClassTargetFullName;
+ if (!classContext.forSmartPointer())
+ computedClassTargetFullName = getClassTargetFullName(metaClass);
+ else
+ computedClassTargetFullName = getClassTargetFullName(classContext.preciseType());
+
+ s << INDENT << "/*tp_name*/ \"" << computedClassTargetFullName << "\"," << endl;
s << INDENT << "/*tp_basicsize*/ sizeof(SbkObject)," << endl;
s << INDENT << "/*tp_itemsize*/ 0," << endl;
s << INDENT << "/*tp_dealloc*/ " << tp_dealloc << ',' << endl;
@@ -3565,7 +3734,9 @@ void CppGenerator::writeClassDefinition(QTextStream& s, const AbstractMetaClass*
s << "} //extern" << endl;
}
-void CppGenerator::writeMappingMethods(QTextStream& s, const AbstractMetaClass* metaClass)
+void CppGenerator::writeMappingMethods(QTextStream &s,
+ const AbstractMetaClass *metaClass,
+ GeneratorContext &context)
{
QMap<QString, QString> funcs;
@@ -3583,7 +3754,7 @@ void CppGenerator::writeMappingMethods(QTextStream& s, const AbstractMetaClass*
s << funcRetVal << ' ' << funcName << '(' << funcArgs << ')' << endl << '{' << endl;
writeInvalidPyObjectCheck(s, QLatin1String(PYTHON_SELF_VAR));
- writeCppSelfDefinition(s, func);
+ writeCppSelfDefinition(s, func, context);
const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last();
writeCodeSnips(s, snips, TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode, func, lastArg);
@@ -3591,7 +3762,9 @@ void CppGenerator::writeMappingMethods(QTextStream& s, const AbstractMetaClass*
}
}
-void CppGenerator::writeSequenceMethods(QTextStream& s, const AbstractMetaClass* metaClass)
+void CppGenerator::writeSequenceMethods(QTextStream &s,
+ const AbstractMetaClass *metaClass,
+ GeneratorContext &context)
{
QMap<QString, QString> funcs;
@@ -3611,7 +3784,7 @@ void CppGenerator::writeSequenceMethods(QTextStream& s, const AbstractMetaClass*
s << funcRetVal << ' ' << funcName << '(' << funcArgs << ')' << endl << '{' << endl;
writeInvalidPyObjectCheck(s, QLatin1String(PYTHON_SELF_VAR));
- writeCppSelfDefinition(s, func);
+ writeCppSelfDefinition(s, func, context);
const AbstractMetaArgument* lastArg = func->arguments().isEmpty() ? 0 : func->arguments().last();
writeCodeSnips(s, snips,TypeSystem::CodeSnipPositionAny, TypeSystem::TargetLangCode, func, lastArg);
@@ -3619,7 +3792,7 @@ void CppGenerator::writeSequenceMethods(QTextStream& s, const AbstractMetaClass*
}
if (!injectedCode)
- writeStdListWrapperMethods(s, metaClass);
+ writeStdListWrapperMethods(s, context);
}
void CppGenerator::writeTypeAsSequenceDefinition(QTextStream& s, const AbstractMetaClass* metaClass)
@@ -3775,14 +3948,21 @@ void CppGenerator::writeTpClearFunction(QTextStream& s, const AbstractMetaClass*
s << '}' << endl;
}
-void CppGenerator::writeCopyFunction(QTextStream& s, const AbstractMetaClass* metaClass)
+void CppGenerator::writeCopyFunction(QTextStream &s, GeneratorContext &context)
{
+ const AbstractMetaClass *metaClass = context.metaClass();
QString className = cpythonTypeName(metaClass);
className.remove(QRegExp(QLatin1String("_Type$")));
s << "static PyObject* " << className << "___copy__(PyObject* " PYTHON_SELF_VAR ")" << endl;
s << "{" << endl;
- writeCppSelfDefinition(s, metaClass, false, true);
- s << INDENT << "PyObject* " << PYTHON_RETURN_VAR << " = " << cpythonToPythonConversionFunction(metaClass);
+ writeCppSelfDefinition(s, context, false, true);
+ QString conversionCode;
+ if (!context.forSmartPointer())
+ conversionCode = cpythonToPythonConversionFunction(metaClass);
+ else
+ conversionCode = cpythonToPythonConversionFunction(context.preciseType());
+
+ s << INDENT << "PyObject* " << PYTHON_RETURN_VAR << " = " << conversionCode;
s << CPP_SELF_VAR ");" << endl;
writeFunctionReturnErrorCheckSection(s);
s << INDENT << "return " PYTHON_RETURN_VAR ";" << endl;
@@ -3790,13 +3970,15 @@ void CppGenerator::writeCopyFunction(QTextStream& s, const AbstractMetaClass* me
s << endl;
}
-void CppGenerator::writeGetterFunction(QTextStream& s, const AbstractMetaField* metaField)
+void CppGenerator::writeGetterFunction(QTextStream &s,
+ const AbstractMetaField *metaField,
+ GeneratorContext &context)
{
ErrorCode errorCode(0);
s << "static PyObject* " << cpythonGetterFunctionName(metaField) << "(PyObject* " PYTHON_SELF_VAR ", void*)" << endl;
s << '{' << endl;
- writeCppSelfDefinition(s, metaField->enclosingClass());
+ writeCppSelfDefinition(s, context);
AbstractMetaType* fieldType = metaField->type();
// Force use of pointer to return internal variable memory
@@ -3819,7 +4001,7 @@ void CppGenerator::writeGetterFunction(QTextStream& s, const AbstractMetaField*
cppField = QLatin1String("cppOut_local");
} else if (avoidProtectedHack() && metaField->isProtected()) {
s << INDENT << getFullTypeNameWithoutModifiers(fieldType);
- if (fieldType->isContainer() || fieldType->isFlags()) {
+ if (fieldType->isContainer() || fieldType->isFlags() || fieldType->isSmartPointer()) {
s << '&';
cppField.prepend(QLatin1Char('*'));
} else if ((!fieldType->isConstant() && !fieldType->isEnum() && !fieldType->isPrimitive()) || fieldType->indirections() == 1) {
@@ -3843,13 +4025,15 @@ void CppGenerator::writeGetterFunction(QTextStream& s, const AbstractMetaField*
s << '}' << endl;
}
-void CppGenerator::writeSetterFunction(QTextStream& s, const AbstractMetaField* metaField)
+void CppGenerator::writeSetterFunction(QTextStream &s,
+ const AbstractMetaField *metaField,
+ GeneratorContext &context)
{
ErrorCode errorCode(0);
s << "static int " << cpythonSetterFunctionName(metaField) << "(PyObject* " PYTHON_SELF_VAR ", PyObject* pyIn, void*)" << endl;
s << '{' << endl;
- writeCppSelfDefinition(s, metaField->enclosingClass());
+ writeCppSelfDefinition(s, context);
s << INDENT << "if (pyIn == 0) {" << endl;
{
@@ -3904,13 +4088,14 @@ void CppGenerator::writeSetterFunction(QTextStream& s, const AbstractMetaField*
s << '}' << endl;
}
-void CppGenerator::writeRichCompareFunction(QTextStream& s, const AbstractMetaClass* metaClass)
+void CppGenerator::writeRichCompareFunction(QTextStream &s, GeneratorContext &context)
{
+ const AbstractMetaClass *metaClass = context.metaClass();
QString baseName = cpythonBaseName(metaClass);
s << "static PyObject* ";
s << baseName << "_richcompare(PyObject* " PYTHON_SELF_VAR ", PyObject* " PYTHON_ARG ", int op)" << endl;
s << '{' << endl;
- writeCppSelfDefinition(s, metaClass, false, true);
+ writeCppSelfDefinition(s, context, false, true);
writeUnusedVariableCast(s, QLatin1String(CPP_SELF_VAR));
s << INDENT << "PyObject* " PYTHON_RETURN_VAR " = 0;" << endl;
s << INDENT << "PythonToCppFunc " PYTHON_TO_CPP_VAR << ';' << endl;
@@ -4350,7 +4535,21 @@ void CppGenerator::writeFlagsUnaryOperator(QTextStream& s, const AbstractMetaEnu
s << '}' << endl << endl;
}
-void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* metaClass)
+QString CppGenerator::getInitFunctionName(GeneratorContext &context) const
+{
+ QString initFunctionName;
+ if (!context.forSmartPointer()) {
+ initFunctionName = context.metaClass()->qualifiedCppName();
+ initFunctionName.replace(QLatin1String("::"), QLatin1String("_"));
+ } else {
+ initFunctionName = getFilteredCppSignatureString(context.preciseType()->cppSignature());
+ }
+ return initFunctionName;
+}
+
+void CppGenerator::writeClassRegister(QTextStream &s,
+ const AbstractMetaClass *metaClass,
+ GeneratorContext &classContext)
{
const ComplexTypeEntry* classTypeEntry = metaClass->typeEntry();
@@ -4359,7 +4558,8 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m
QString enclosingObjectVariable = hasEnclosingClass ? QLatin1String("enclosingClass") : QLatin1String("module");
QString pyTypeName = cpythonTypeName(metaClass);
- s << "void init_" << metaClass->qualifiedCppName().replace(QLatin1String("::"), QLatin1String("_"));
+ QString initFunctionName = getInitFunctionName(classContext);
+ s << "void init_" << initFunctionName;
s << "(PyObject* " << enclosingObjectVariable << ")" << endl;
s << '{' << endl;
@@ -4384,7 +4584,11 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m
s << endl;
}
- s << INDENT << cpythonTypeNameExt(classTypeEntry);
+ if (!classContext.forSmartPointer())
+ s << INDENT << cpythonTypeNameExt(classTypeEntry);
+ else
+ s << INDENT << cpythonTypeNameExt(classContext.preciseType());
+
s << " = reinterpret_cast<PyTypeObject*>(&" << pyTypeName << ");" << endl;
s << endl;
@@ -4405,9 +4609,20 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m
// Create type and insert it in the module or enclosing class.
s << INDENT << "if (!Shiboken::ObjectType::introduceWrapperType(" << enclosingObjectVariable;
- s << ", \"" << metaClass->name() << "\", \"";
+ QString typeName;
+ if (!classContext.forSmartPointer())
+ typeName = metaClass->name();
+ else
+ typeName = classContext.preciseType()->cppSignature();
+
+ s << ", \"" << typeName << "\", \"";
+
// Original name
- s << metaClass->qualifiedCppName() << (isObjectType(classTypeEntry) ? "*" : "");
+ if (!classContext.forSmartPointer())
+ s << metaClass->qualifiedCppName() << (isObjectType(classTypeEntry) ? "*" : "");
+ else
+ s << classContext.preciseType()->cppSignature();
+
s << "\"," << endl;
{
Indentation indent(INDENT);
@@ -4418,6 +4633,9 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m
QString dtorClassName = metaClass->qualifiedCppName();
if ((avoidProtectedHack() && metaClass->hasProtectedDestructor()) || classTypeEntry->isValue())
dtorClassName = wrapperName(metaClass);
+ if (classContext.forSmartPointer())
+ dtorClassName = wrapperName(classContext.preciseType());
+
s << ", &Shiboken::callCppDestructor< ::" << dtorClassName << " >";
} else if (metaClass->baseClass() || hasEnclosingClass) {
s << ", 0";
@@ -4442,7 +4660,7 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m
s << INDENT << '}' << endl << endl;
// Register conversions for the type.
- writeConverterRegister(s, metaClass);
+ writeConverterRegister(s, metaClass, classContext);
s << endl;
// class inject-code target/beginning
@@ -4504,7 +4722,7 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m
if (avoidProtectedHack() && shouldGenerateCppWrapper(metaClass))
s << INDENT << wrapperName(metaClass) << "::pysideInitQtMetaTypes();\n";
else
- writeInitQtMetaTypeFunctionBody(s, metaClass);
+ writeInitQtMetaTypeFunctionBody(s, classContext);
}
if (usePySideExtensions() && metaClass->isQObject()) {
@@ -4516,11 +4734,16 @@ void CppGenerator::writeClassRegister(QTextStream& s, const AbstractMetaClass* m
s << '}' << endl;
}
-void CppGenerator::writeInitQtMetaTypeFunctionBody(QTextStream& s, const AbstractMetaClass* metaClass) const
+void CppGenerator::writeInitQtMetaTypeFunctionBody(QTextStream &s, GeneratorContext &context) const
{
+ const AbstractMetaClass* metaClass = context.metaClass();
// Gets all class name variants used on different possible scopes
QStringList nameVariants;
- nameVariants << metaClass->name();
+ if (!context.forSmartPointer())
+ nameVariants << metaClass->name();
+ else
+ nameVariants << context.preciseType()->cppSignature();
+
const AbstractMetaClass* enclosingClass = metaClass->enclosingClass();
while (enclosingClass) {
if (enclosingClass->typeEntry()->generateCode())
@@ -4528,7 +4751,12 @@ void CppGenerator::writeInitQtMetaTypeFunctionBody(QTextStream& s, const Abstrac
enclosingClass = enclosingClass->enclosingClass();
}
- const QString className = metaClass->qualifiedCppName();
+ QString className;
+ if (!context.forSmartPointer())
+ className = metaClass->qualifiedCppName();
+ else
+ className = context.preciseType()->cppSignature();
+
if (!metaClass->isNamespace() && !metaClass->isAbstract()) {
// Qt metatypes are registered only on their first use, so we do this now.
bool canBeValue = false;
@@ -4610,8 +4838,13 @@ void CppGenerator::writeTypeDiscoveryFunction(QTextStream& s, const AbstractMeta
s << "}\n\n";
}
-void CppGenerator::writeSetattroFunction(QTextStream& s, const AbstractMetaClass* metaClass)
+QString CppGenerator::writeSmartPointerGetterCast() {
+ return QStringLiteral("const_cast<char *>(" SMART_POINTER_GETTER ")");
+}
+
+void CppGenerator::writeSetattroFunction(QTextStream &s, GeneratorContext &context)
{
+ const AbstractMetaClass* metaClass = context.metaClass();
s << "static int " << cpythonSetattroFunctionName(metaClass) << "(PyObject* " PYTHON_SELF_VAR ", PyObject* name, PyObject* value)" << endl;
s << '{' << endl;
if (usePySideExtensions()) {
@@ -4620,6 +4853,27 @@ void CppGenerator::writeSetattroFunction(QTextStream& s, const AbstractMetaClass
Indentation indent(INDENT);
s << INDENT << "return PySide::Property::setValue(reinterpret_cast<PySideProperty*>(pp.object()), " PYTHON_SELF_VAR ", value);" << endl;
}
+
+ if (context.forSmartPointer()) {
+ s << INDENT << "// Try to find the 'name' attribute, by retrieving the PyObject for the corresponding C++ object held by the smart pointer." << endl;
+ s << INDENT << "PyObject *rawObj = PyObject_CallMethod(" PYTHON_SELF_VAR ", "
+ << writeSmartPointerGetterCast() << ", 0);" << endl;
+ s << INDENT << "if (rawObj) {" << endl;
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "int hasAttribute = PyObject_HasAttr(rawObj, name);" << endl;
+ s << INDENT << "if (hasAttribute) {" << endl;
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "return PyObject_GenericSetAttr(rawObj, name, value);" << endl;
+ }
+ s << INDENT << '}' << endl;
+ s << INDENT << "Py_DECREF(rawObj);" << endl;
+ }
+ s << INDENT << '}' << endl;
+
+ }
+
s << INDENT << "return PyObject_GenericSetAttr(" PYTHON_SELF_VAR ", name, value);" << endl;
s << '}' << endl;
}
@@ -4627,8 +4881,9 @@ void CppGenerator::writeSetattroFunction(QTextStream& s, const AbstractMetaClass
static inline QString qObjectClassName() { return QStringLiteral("QObject"); }
static inline QString qMetaObjectClassName() { return QStringLiteral("QMetaObject"); }
-void CppGenerator::writeGetattroFunction(QTextStream& s, const AbstractMetaClass* metaClass)
+void CppGenerator::writeGetattroFunction(QTextStream& s, GeneratorContext &context)
{
+ const AbstractMetaClass* metaClass = context.metaClass();
s << "static PyObject* " << cpythonGetattroFunctionName(metaClass) << "(PyObject* " PYTHON_SELF_VAR ", PyObject* name)" << endl;
s << '{' << endl;
@@ -4690,7 +4945,59 @@ void CppGenerator::writeGetattroFunction(QTextStream& s, const AbstractMetaClass
}
s << INDENT << '}' << endl;
}
- s << INDENT << "return " << getattrFunc << ';' << endl;
+
+ if (context.forSmartPointer()) {
+ s << INDENT << "PyObject *tmp = " << getattrFunc << ';' << endl;
+ s << INDENT << "if (tmp) {" << endl;
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "return tmp;" << endl;
+ }
+ s << INDENT << "} else {" << endl;
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "if (!PyErr_ExceptionMatches(PyExc_AttributeError)) return NULL;" << endl;
+ s << INDENT << "PyErr_Clear();" << endl;
+
+ s << INDENT << "// Try to find the 'name' attribute, by retrieving the PyObject for "
+ "the corresponding C++ object held by the smart pointer." << endl;
+ s << INDENT << "PyObject *rawObj = PyObject_CallMethod(" PYTHON_SELF_VAR ", "
+ << writeSmartPointerGetterCast() << ", 0);" << endl;
+ s << INDENT << "if (rawObj) {" << endl;
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "PyObject *attribute = PyObject_GetAttr(rawObj, name);" << endl;
+ s << INDENT << "if (attribute) {" << endl;
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "tmp = attribute;" << endl;
+ }
+ s << INDENT << '}' << endl;
+ s << INDENT << "Py_DECREF(rawObj);" << endl;
+ }
+ s << INDENT << '}' << endl;
+ s << INDENT << "if (!tmp) {" << endl;
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "PyTypeObject *tp = Py_TYPE(self);" << endl;
+ s << INDENT << "PyErr_Format(PyExc_AttributeError," << endl;
+ s << INDENT << " \"'%.50s' object has no attribute '%.400s'\"," << endl;
+ s << INDENT << " tp->tp_name, PyBytes_AS_STRING(name));" << endl;
+ s << INDENT << "return NULL;" << endl;
+ }
+ s << INDENT << "} else {" << endl;
+ {
+ Indentation indent(INDENT);
+ s << INDENT << "return tmp;" << endl;
+ }
+ s << INDENT << '}' << endl;
+
+ }
+ s << INDENT << '}' << endl;
+
+ } else {
+ s << INDENT << "return " << getattrFunc << ';' << endl;
+ }
s << '}' << endl;
}
@@ -4724,7 +5031,9 @@ bool CppGenerator::finishGeneration()
if (overloads.isEmpty())
continue;
- writeMethodWrapper(s_globalFunctionImpl, overloads);
+ // Dummy context to satisfy the API.
+ GeneratorContext classContext;
+ writeMethodWrapper(s_globalFunctionImpl, overloads, classContext);
writeMethodDefinition(s_globalFunctionDef, overloads);
}
@@ -4756,6 +5065,16 @@ bool CppGenerator::finishGeneration()
s_classPythonDefines << INDENT << defineStr << endl;
}
+ // Initialize smart pointer types.
+ foreach (const AbstractMetaType *metaType, instantiatedSmartPointers()) {
+ GeneratorContext context(0, metaType, true);
+ QString initFunctionName = getInitFunctionName(context);
+ s_classInitDecl << "void init_" << initFunctionName << "(PyObject* module);" << endl;
+ QString defineStr = QLatin1String("init_") + initFunctionName;
+ defineStr += QLatin1String("(module);");
+ s_classPythonDefines << INDENT << defineStr << endl;
+ }
+
QString moduleFileName(outputDirectory() + QLatin1Char('/') + subDirectoryForPackage(packageName()));
moduleFileName += QLatin1Char('/') + moduleName().toLower() + QLatin1String("_module_wrapper.cpp");
@@ -4968,7 +5287,7 @@ bool CppGenerator::finishGeneration()
s << INDENT << "}" << endl << endl;
}
- int maxTypeIndex = getMaxTypeIndex();
+ int maxTypeIndex = getMaxTypeIndex() + instantiatedSmartPointers().size();
if (maxTypeIndex) {
s << INDENT << "// Create an array of wrapper types for the current module." << endl;
s << INDENT << "static PyTypeObject* cppApi[SBK_" << moduleName() << "_IDX_COUNT];" << endl;
@@ -5191,30 +5510,32 @@ void CppGenerator::writeReturnValueHeuristics(QTextStream& s, const AbstractMeta
}
}
-void CppGenerator::writeHashFunction(QTextStream& s, const AbstractMetaClass* metaClass)
+void CppGenerator::writeHashFunction(QTextStream &s, GeneratorContext &context)
{
+ const AbstractMetaClass *metaClass = context.metaClass();
s << "static Py_hash_t " << cpythonBaseName(metaClass) << "_HashFunc(PyObject* self) {" << endl;
- writeCppSelfDefinition(s, metaClass);
+ writeCppSelfDefinition(s, context);
s << INDENT << "return " << metaClass->typeEntry()->hashFunction() << '(';
s << (isObjectType(metaClass) ? "" : "*") << CPP_SELF_VAR << ");" << endl;
s << '}' << endl << endl;
}
-void CppGenerator::writeStdListWrapperMethods(QTextStream& s, const AbstractMetaClass* metaClass)
+void CppGenerator::writeStdListWrapperMethods(QTextStream &s, GeneratorContext &context)
{
+ const AbstractMetaClass *metaClass = context.metaClass();
ErrorCode errorCode(0);
// __len__
s << "Py_ssize_t " << cpythonBaseName(metaClass->typeEntry()) << "__len__(PyObject* " PYTHON_SELF_VAR ")" << endl;
s << '{' << endl;
- writeCppSelfDefinition(s, metaClass);
+ writeCppSelfDefinition(s, context);
s << INDENT << "return " CPP_SELF_VAR "->size();" << endl;
s << '}' << endl;
// __getitem__
s << "PyObject* " << cpythonBaseName(metaClass->typeEntry()) << "__getitem__(PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i)" << endl;
s << '{' << endl;
- writeCppSelfDefinition(s, metaClass);
+ writeCppSelfDefinition(s, context);
writeIndexError(s, QLatin1String("index out of bounds"));
s << INDENT << metaClass->qualifiedCppName() << "::iterator _item = " CPP_SELF_VAR "->begin();" << endl;
@@ -5231,7 +5552,7 @@ void CppGenerator::writeStdListWrapperMethods(QTextStream& s, const AbstractMeta
ErrorCode errorCode2(-1);
s << "int " << cpythonBaseName(metaClass->typeEntry()) << "__setitem__(PyObject* " PYTHON_SELF_VAR ", Py_ssize_t _i, PyObject* pyArg)" << endl;
s << '{' << endl;
- writeCppSelfDefinition(s, metaClass);
+ writeCppSelfDefinition(s, context);
writeIndexError(s, QLatin1String("list assignment index out of range"));
s << INDENT << "PythonToCppFunc " << PYTHON_TO_CPP_VAR << ';' << endl;
@@ -5264,14 +5585,15 @@ void CppGenerator::writeIndexError(QTextStream& s, const QString& errorMsg)
s << INDENT << '}' << endl;
}
-QString CppGenerator::writeReprFunction(QTextStream& s, const AbstractMetaClass* metaClass)
+QString CppGenerator::writeReprFunction(QTextStream &s, GeneratorContext &context)
{
+ const AbstractMetaClass *metaClass = context.metaClass();
QString funcName = cpythonBaseName(metaClass) + QLatin1String("__repr__");
s << "extern \"C\"" << endl;
s << '{' << endl;
s << "static PyObject* " << funcName << "(PyObject* self)" << endl;
s << '{' << endl;
- writeCppSelfDefinition(s, metaClass);
+ writeCppSelfDefinition(s, context);
s << INDENT << "QBuffer buffer;" << endl;
s << INDENT << "buffer.open(QBuffer::ReadWrite);" << endl;
s << INDENT << "QDebug dbg(&buffer);" << endl;
diff --git a/generator/shiboken2/cppgenerator.h b/generator/shiboken2/cppgenerator.h
index 104ab41..5dc3f5a 100644
--- a/generator/shiboken2/cppgenerator.h
+++ b/generator/shiboken2/cppgenerator.h
@@ -39,10 +39,11 @@ class CppGenerator : public ShibokenGenerator
public:
CppGenerator();
protected:
- QString fileNameForClass(const AbstractMetaClass* metaClass) const;
+ QString fileNamePrefix() const;
+ QString fileNameForContext(GeneratorContext &context) const;
QList<AbstractMetaFunctionList> filterGroupedOperatorFunctions(const AbstractMetaClass* metaClass,
uint query);
- void generateClass(QTextStream& s, const AbstractMetaClass* metaClass);
+ void generateClass(QTextStream& s, GeneratorContext &classContext);
bool finishGeneration();
private:
@@ -57,21 +58,31 @@ private:
void writeEnumConverterFunctions(QTextStream& s, const TypeEntry* enumType);
void writeEnumConverterFunctions(QTextStream& s, const AbstractMetaEnum* metaEnum);
- void writeConverterFunctions(QTextStream& s, const AbstractMetaClass* metaClass);
+ void writeConverterFunctions(QTextStream &s, const AbstractMetaClass *metaClass,
+ GeneratorContext &classContext);
void writeCustomConverterFunctions(QTextStream& s, const CustomConversion* customConversion);
- void writeConverterRegister(QTextStream& s, const AbstractMetaClass* metaClass);
+ void writeConverterRegister(QTextStream &s, const AbstractMetaClass *metaClass,
+ GeneratorContext &classContext);
void writeCustomConverterRegister(QTextStream& s, const CustomConversion* customConversion, const QString& converterVar);
void writeContainerConverterRegister(QTextStream& s, const AbstractMetaType* container, const QString& converterVar);
void writeContainerConverterFunctions(QTextStream& s, const AbstractMetaType* containerType);
- void writeMethodWrapperPreamble(QTextStream& s, OverloadData& overloadData);
- void writeConstructorWrapper(QTextStream& s, const AbstractMetaFunctionList overloads);
+ void writeMethodWrapperPreamble(QTextStream &s, OverloadData &overloadData,
+ GeneratorContext &context);
+ void writeConstructorWrapper(QTextStream &s, const AbstractMetaFunctionList overloads, GeneratorContext &classContext);
void writeDestructorWrapper(QTextStream& s, const AbstractMetaClass* metaClass);
- void writeMethodWrapper(QTextStream& s, const AbstractMetaFunctionList overloads);
+ void writeMethodWrapper(QTextStream &s, const AbstractMetaFunctionList overloads,
+ GeneratorContext &classContext);
void writeArgumentsInitializer(QTextStream& s, OverloadData& overloadData);
- void writeCppSelfDefinition(QTextStream& s, const AbstractMetaFunction* func, bool hasStaticOverload = false);
- void writeCppSelfDefinition(QTextStream& s, const AbstractMetaClass* metaClass, bool hasStaticOverload = false, bool cppSelfAsReference = false);
+ void writeCppSelfDefinition(QTextStream &s,
+ const AbstractMetaFunction *func,
+ GeneratorContext &context,
+ bool hasStaticOverload = false);
+ void writeCppSelfDefinition(QTextStream &s,
+ GeneratorContext &context,
+ bool hasStaticOverload = false,
+ bool cppSelfAsReference = false);
void writeErrorSection(QTextStream& s, OverloadData& overloadData);
void writeFunctionReturnErrorCheckSection(QTextStream& s, bool hasReturnValue = true);
@@ -84,8 +95,9 @@ private:
void writeTypeDiscoveryFunction(QTextStream& s, const AbstractMetaClass* metaClass);
- void writeSetattroFunction(QTextStream& s, const AbstractMetaClass* metaClass);
- void writeGetattroFunction(QTextStream& s, const AbstractMetaClass* metaClass);
+ void writeSetattroFunction(QTextStream &s, GeneratorContext &context);
+ void writeGetattroFunction(QTextStream &s, GeneratorContext &context);
+ QString writeSmartPointerGetterCast();
/**
* Writes Python to C++ conversions for arguments on Python wrappers.
@@ -152,10 +164,15 @@ private:
void writeOverloadedFunctionDecisorEngine(QTextStream& s, const OverloadData* parentOverloadData);
/// Writes calls to all the possible method/function overloads.
- void writeFunctionCalls(QTextStream& s, const OverloadData& overloadData);
+ void writeFunctionCalls(QTextStream &s,
+ const OverloadData &overloadData,
+ GeneratorContext &context);
/// Writes the call to a single function usually from a collection of overloads.
- void writeSingleFunctionCall(QTextStream& s, const OverloadData& overloadData, const AbstractMetaFunction* func);
+ void writeSingleFunctionCall(QTextStream &s,
+ const OverloadData &overloadData,
+ const AbstractMetaFunction *func,
+ GeneratorContext &context);
/// Returns the name of a C++ to Python conversion function.
static QString cppToPythonFunctionName(const QString& sourceTypeName, QString targetTypeName = QString());
@@ -207,32 +224,47 @@ private:
/// Returns a string containing the name of an argument for the given function and argument index.
QString argumentNameFromIndex(const AbstractMetaFunction* func, int argIndex, const AbstractMetaClass** wrappedClass);
- void writeMethodCall(QTextStream& s, const AbstractMetaFunction* func, int maxArgs = 0);
+ void writeMethodCall(QTextStream &s, const AbstractMetaFunction *func,
+ GeneratorContext &context, int maxArgs = 0);
- void writeClassRegister(QTextStream& s, const AbstractMetaClass* metaClass);
- void writeClassDefinition(QTextStream& s, const AbstractMetaClass* metaClass);
+ QString getInitFunctionName(GeneratorContext &context) const;
+
+ void writeClassRegister(QTextStream &s,
+ const AbstractMetaClass *metaClass,
+ GeneratorContext &classContext);
+ void writeClassDefinition(QTextStream &s,
+ const AbstractMetaClass *metaClass,
+ GeneratorContext &classContext);
void writeMethodDefinitionEntry(QTextStream& s, const AbstractMetaFunctionList overloads);
void writeMethodDefinition(QTextStream& s, const AbstractMetaFunctionList overloads);
/// Writes the implementation of all methods part of python sequence protocol
- void writeSequenceMethods(QTextStream& s, const AbstractMetaClass* metaClass);
+ void writeSequenceMethods(QTextStream &s,
+ const AbstractMetaClass *metaClass,
+ GeneratorContext &context);
void writeTypeAsSequenceDefinition(QTextStream& s, const AbstractMetaClass* metaClass);
/// Writes the PyMappingMethods structure for types that supports the python mapping protocol.
void writeTypeAsMappingDefinition(QTextStream& s, const AbstractMetaClass* metaClass);
- void writeMappingMethods(QTextStream& s, const AbstractMetaClass* metaClass);
+ void writeMappingMethods(QTextStream &s,
+ const AbstractMetaClass *metaClass,
+ GeneratorContext &context);
void writeTypeAsNumberDefinition(QTextStream& s, const AbstractMetaClass* metaClass);
void writeTpTraverseFunction(QTextStream& s, const AbstractMetaClass* metaClass);
void writeTpClearFunction(QTextStream& s, const AbstractMetaClass* metaClass);
- void writeCopyFunction(QTextStream& s, const AbstractMetaClass *metaClass);
+ void writeCopyFunction(QTextStream &s, GeneratorContext &context);
- void writeGetterFunction(QTextStream& s, const AbstractMetaField* metaField);
- void writeSetterFunction(QTextStream& s, const AbstractMetaField* metaField);
+ void writeGetterFunction(QTextStream &s,
+ const AbstractMetaField *metaField,
+ GeneratorContext &context);
+ void writeSetterFunction(QTextStream &s,
+ const AbstractMetaField *metaField,
+ GeneratorContext &context);
- void writeRichCompareFunction(QTextStream& s, const AbstractMetaClass* metaClass);
+ void writeRichCompareFunction(QTextStream &s, GeneratorContext &context);
void writeToPythonFunction(QTextStream& s, const AbstractMetaClass* metaClass);
void writeEnumsInitialization(QTextStream& s, AbstractMetaEnumList& enums);
@@ -263,7 +295,7 @@ private:
void writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, bool userHeuristicForReturn);
bool writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, int argIndex, bool userHeuristicPolicy);
void writeReturnValueHeuristics(QTextStream& s, const AbstractMetaFunction* func, const QString& self = QLatin1String(PYTHON_SELF_VAR));
- void writeInitQtMetaTypeFunctionBody(QTextStream& s, const AbstractMetaClass* metaClass) const;
+ void writeInitQtMetaTypeFunctionBody(QTextStream &s, GeneratorContext &context) const;
/**
* Returns the multiple inheritance initializer function for the given class.
@@ -288,14 +320,14 @@ private:
/// Returns true if generator should produce getters and setters for the given class.
bool shouldGenerateGetSetList(const AbstractMetaClass* metaClass);
- void writeHashFunction(QTextStream& s, const AbstractMetaClass* metaClass);
+ void writeHashFunction(QTextStream &s, GeneratorContext &context);
/// Write default implementations for sequence protocol
- void writeStdListWrapperMethods(QTextStream& s, const AbstractMetaClass* metaClass);
+ void writeStdListWrapperMethods(QTextStream &s, GeneratorContext &context);
/// Helper function for writeStdListWrapperMethods.
void writeIndexError(QTextStream& s, const QString& errorMsg);
- QString writeReprFunction(QTextStream& s, const AbstractMetaClass* metaClass);
+ QString writeReprFunction(QTextStream &s, GeneratorContext &context);
bool hasBoolCast(const AbstractMetaClass* metaClass) const;
diff --git a/generator/shiboken2/headergenerator.cpp b/generator/shiboken2/headergenerator.cpp
index 950e938..ea308f5 100644
--- a/generator/shiboken2/headergenerator.cpp
+++ b/generator/shiboken2/headergenerator.cpp
@@ -38,11 +38,23 @@
#include <QtCore/QRegExp>
#include <QtCore/QDebug>
-QString HeaderGenerator::fileNameForClass(const AbstractMetaClass* metaClass) const
+QString HeaderGenerator::fileNamePrefix() const
{
- QString result = metaClass->qualifiedCppName().toLower();
- result.replace(QLatin1String("::"), QLatin1String("_"));
- return result + QLatin1String("_wrapper.h");
+ return QLatin1String("_wrapper.h");
+}
+
+QString HeaderGenerator::fileNameForContext(GeneratorContext &context) const
+{
+ const AbstractMetaClass *metaClass = context.metaClass();
+ if (!context.forSmartPointer()) {
+ QString fileNameBase = metaClass->qualifiedCppName().toLower();
+ fileNameBase.replace(QLatin1String("::"), QLatin1String("_"));
+ return fileNameBase + fileNamePrefix();
+ } else {
+ const AbstractMetaType *smartPointerType = context.preciseType();
+ QString fileNameBase = getFileNameBaseForSmartPointer(smartPointerType, metaClass);
+ return fileNameBase + fileNamePrefix();
+ }
}
void HeaderGenerator::writeCopyCtor(QTextStream& s, const AbstractMetaClass* metaClass) const
@@ -78,8 +90,9 @@ void HeaderGenerator::writeProtectedFieldAccessors(QTextStream& s, const Abstrac
<< " { " << fieldName << " = value; }" << endl;
}
-void HeaderGenerator::generateClass(QTextStream& s, const AbstractMetaClass* metaClass)
+void HeaderGenerator::generateClass(QTextStream &s, GeneratorContext &classContext)
{
+ AbstractMetaClass *metaClass = classContext.metaClass();
if (ReportHandler::isDebug(ReportHandler::SparseDebug))
qCDebug(lcShiboken) << "Generating header for " << metaClass->fullName();
m_inheritedOverloads.clear();
@@ -88,8 +101,13 @@ void HeaderGenerator::generateClass(QTextStream& s, const AbstractMetaClass* met
// write license comment
s << licenseComment();
- QString wrapperName = HeaderGenerator::wrapperName(metaClass);
- QString headerGuard = wrapperName.replace(QLatin1String("::"), QLatin1String("_")).toUpper();
+ QString wrapperName;
+ if (!classContext.forSmartPointer()) {
+ wrapperName = HeaderGenerator::wrapperName(metaClass);
+ } else {
+ wrapperName = HeaderGenerator::wrapperName(classContext.preciseType());
+ }
+ QString headerGuard = getFilteredCppSignatureString(wrapperName).toUpper();
// Header
s << "#ifndef SBK_" << headerGuard << "_H" << endl;
@@ -297,17 +315,35 @@ bool HeaderGenerator::finishGeneration()
writeTypeIndexDefine(macrosStream, metaClass);
lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass);
}
+
foreach (const AbstractMetaEnum* metaEnum, globalEnums)
writeTypeIndexDefineLine(macrosStream, metaEnum->typeEntry());
+
+ // Write the smart pointer define indexes.
+ int smartPointerCountIndex = getMaxTypeIndex();
+ int smartPointerCount = 0;
+ foreach (const AbstractMetaType *metaType, instantiatedSmartPointers()) {
+ QString variableName = getTypeIndexVariableName(metaType);
+ macrosStream << "#define ";
+ macrosStream.setFieldWidth(60);
+ macrosStream << variableName;
+ macrosStream.setFieldWidth(0);
+ macrosStream << ' ' << smartPointerCountIndex << " // " << metaType->cppSignature()
+ << endl;
+ ++smartPointerCountIndex;
+ ++smartPointerCount;
+ }
+
+
macrosStream << "#define ";
macrosStream.setFieldWidth(60);
macrosStream << QLatin1String("SBK_") + moduleName() + QLatin1String("_IDX_COUNT");
macrosStream.setFieldWidth(0);
- macrosStream << ' ' << getMaxTypeIndex() << endl << endl;
+ macrosStream << ' ' << getMaxTypeIndex() + smartPointerCount << endl << endl;
macrosStream << "// This variable stores all Python types exported by this module." << endl;
macrosStream << "extern PyTypeObject** " << cppApiVariableName() << ';' << endl << endl;
macrosStream << "// This variable stores all type converters exported by this module." << endl;
- macrosStream << "extern SbkConverter** " << convertersVariableName() << ';' << endl << endl;;
+ macrosStream << "extern SbkConverter** " << convertersVariableName() << ';' << endl << endl;
// TODO-CONVERTER ------------------------------------------------------------------------------
// Using a counter would not do, a fix must be made to APIExtractor's getTypeIndex().
@@ -375,6 +411,12 @@ bool HeaderGenerator::finishGeneration()
writeSbkTypeFunction(typeFunctions, metaClass);
}
+ foreach (const AbstractMetaType *metaType, instantiatedSmartPointers()) {
+ const TypeEntry *classType = metaType->typeEntry();
+ includes << classType->include();
+ writeSbkTypeFunction(typeFunctions, metaType);
+ }
+
QString moduleHeaderFileName(outputDirectory()
+ QDir::separator() + subDirectoryForPackage(packageName())
+ QDir::separator() + getModuleHeaderFileName());
@@ -480,6 +522,12 @@ void HeaderGenerator::writeSbkTypeFunction(QTextStream& s, const AbstractMetaCla
<< "{ return reinterpret_cast<PyTypeObject*>(" << cpythonTypeNameExt(cppClass->typeEntry()) << "); }\n";
}
+void HeaderGenerator::writeSbkTypeFunction(QTextStream &s, const AbstractMetaType *metaType)
+{
+ s << "template<> inline PyTypeObject* SbkType< ::" << metaType->cppSignature() << " >() "
+ << "{ return reinterpret_cast<PyTypeObject*>(" << cpythonTypeNameExt(metaType) << "); }\n";
+}
+
void HeaderGenerator::writeInheritedOverloads(QTextStream& s)
{
foreach (const AbstractMetaFunction* func, m_inheritedOverloads) {
diff --git a/generator/shiboken2/headergenerator.h b/generator/shiboken2/headergenerator.h
index 3652ee4..72dcbf6 100644
--- a/generator/shiboken2/headergenerator.h
+++ b/generator/shiboken2/headergenerator.h
@@ -43,8 +43,9 @@ class HeaderGenerator : public ShibokenGenerator
public:
QMap<QString, QString> options() const { return QMap<QString, QString>(); }
protected:
- QString fileNameForClass(const AbstractMetaClass* metaClass) const;
- void generateClass(QTextStream& s, const AbstractMetaClass* metaClass);
+ QString fileNamePrefix() const;
+ QString fileNameForContext(GeneratorContext &context) const;
+ void generateClass(QTextStream& s, GeneratorContext &classContext);
bool finishGeneration();
private:
@@ -53,6 +54,7 @@ private:
void writeFunction(QTextStream& s, const AbstractMetaFunction* func);
void writeSbkTypeFunction(QTextStream& s, const AbstractMetaEnum* cppEnum);
void writeSbkTypeFunction(QTextStream& s, const AbstractMetaClass* cppClass);
+ void writeSbkTypeFunction(QTextStream &s, const AbstractMetaType *metaType);
void writeTypeIndexDefineLine(QTextStream& s, const TypeEntry* typeEntry);
void writeTypeIndexDefine(QTextStream& s, const AbstractMetaClass* metaClass);
void writeProtectedEnumSurrogate(QTextStream& s, const AbstractMetaEnum* cppEnum);
diff --git a/generator/shiboken2/overloaddata.cpp b/generator/shiboken2/overloaddata.cpp
index 6258488..8731fe9 100644
--- a/generator/shiboken2/overloaddata.cpp
+++ b/generator/shiboken2/overloaddata.cpp
@@ -70,7 +70,7 @@ static QString getTypeName(const OverloadData* ov)
static bool typesAreEqual(const AbstractMetaType* typeA, const AbstractMetaType* typeB)
{
if (typeA->typeEntry() == typeB->typeEntry()) {
- if (typeA->isContainer()) {
+ if (typeA->isContainer() || typeA->isSmartPointer()) {
if (typeA->instantiations().size() != typeB->instantiations().size())
return false;
diff --git a/generator/shiboken2/shibokengenerator.cpp b/generator/shiboken2/shibokengenerator.cpp
index 8985891..ca98441 100644
--- a/generator/shiboken2/shibokengenerator.cpp
+++ b/generator/shiboken2/shibokengenerator.cpp
@@ -305,6 +305,11 @@ QString ShibokenGenerator::wrapperName(const AbstractMetaClass* metaClass) const
}
}
+QString ShibokenGenerator::wrapperName(const AbstractMetaType *metaType) const
+{
+ return metaType->cppSignature();
+}
+
QString ShibokenGenerator::fullPythonFunctionName(const AbstractMetaFunction* func)
{
QString funcName;
@@ -549,9 +554,12 @@ QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaClass* metaClass
return cpythonWrapperCPtr(metaClass->typeEntry(), argName);
}
-QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaType* metaType, QString argName)
+QString ShibokenGenerator::cpythonWrapperCPtr(const AbstractMetaType *metaType, QString argName)
{
- return cpythonWrapperCPtr(metaType->typeEntry(), argName);
+ if (!ShibokenGenerator::isWrapperType(metaType->typeEntry()))
+ return QString();
+ return QStringLiteral("((::%1*)Shiboken::Conversions::cppPointer(%2, (SbkObject*)%3))")
+ .arg(metaType->cppSignature(), cpythonTypeNameExt(metaType), argName);
}
QString ShibokenGenerator::cpythonWrapperCPtr(const TypeEntry* type, QString argName)
@@ -631,6 +639,7 @@ QString ShibokenGenerator::getFormatUnitString(const AbstractMetaFunction* func,
|| arg->type()->isEnum()
|| arg->type()->isFlags()
|| arg->type()->isContainer()
+ || arg->type()->isSmartPointer()
|| arg->type()->referenceType() == LValueReference) {
result += QLatin1Char(objType);
} else if (arg->type()->isPrimitive()) {
@@ -937,16 +946,17 @@ bool ShibokenGenerator::isWrapperType(const TypeEntry* type)
{
if (type->isComplex())
return ShibokenGenerator::isWrapperType((const ComplexTypeEntry*)type);
- return type->isObject() || type->isValue();
+ return type->isObject() || type->isValue() || type->isSmartPointer();
}
bool ShibokenGenerator::isWrapperType(const ComplexTypeEntry* type)
{
- return isObjectType(type) || type->isValue();
+ return isObjectType(type) || type->isValue() || type->isSmartPointer();
}
bool ShibokenGenerator::isWrapperType(const AbstractMetaType* metaType)
{
return isObjectType(metaType)
- || metaType->typeEntry()->isValue();
+ || metaType->typeEntry()->isValue()
+ || metaType->typeEntry()->isSmartPointer();
}
bool ShibokenGenerator::isPointerToWrapperType(const AbstractMetaType* type)
@@ -1227,7 +1237,7 @@ QString ShibokenGenerator::cpythonToPythonConversionFunction(const AbstractMetaT
QString conversion;
if (type->referenceType() == LValueReference && !(type->isValue() && type->isConstant()) && !isPointer(type))
conversion = QLatin1String("reference");
- else if (type->isValue())
+ else if (type->isValue() || type->isSmartPointer())
conversion = QLatin1String("copy");
else
conversion = QLatin1String("pointer");
@@ -2048,6 +2058,8 @@ bool ShibokenGenerator::classNeedsGetattroFunction(const AbstractMetaClass* meta
{
if (!metaClass)
return false;
+ if (metaClass->typeEntry()->isSmartPointer())
+ return true;
const FunctionGroupMap &functionGroup = getFunctionGroups(metaClass);
for (FunctionGroupMapIt it = functionGroup.cbegin(), end = functionGroup.cend(); it != end; ++it) {
AbstractMetaFunctionList overloads;
@@ -2066,6 +2078,15 @@ bool ShibokenGenerator::classNeedsGetattroFunction(const AbstractMetaClass* meta
return false;
}
+bool ShibokenGenerator::classNeedsSetattroFunction(const AbstractMetaClass *metaClass)
+{
+ if (!metaClass)
+ return false;
+ if (metaClass->typeEntry()->isSmartPointer())
+ return true;
+ return false;
+}
+
AbstractMetaFunctionList ShibokenGenerator::getMethodsWithBothStaticAndNonStaticMethods(const AbstractMetaClass* metaClass)
{
AbstractMetaFunctionList methods;
@@ -2416,7 +2437,7 @@ void ShibokenGenerator::collectContainerTypesFromConverterMacros(const QString&
if (code.at(start) != QLatin1Char('%')) {
QString typeString = code.mid(start, end - start);
AbstractMetaType* type = buildAbstractMetaTypeFromString(typeString);
- addInstantiatedContainers(type, type->originalTypeDescription());
+ addInstantiatedContainersAndSmartPointers(type, type->originalTypeDescription());
}
start = end;
}
diff --git a/generator/shiboken2/shibokengenerator.h b/generator/shiboken2/shibokengenerator.h
index 5dc2a29..327ca12 100644
--- a/generator/shiboken2/shibokengenerator.h
+++ b/generator/shiboken2/shibokengenerator.h
@@ -46,6 +46,7 @@
#define MIN_CTOR_ERROR_MSG "Could not find a minimal constructor for type '%1'. "\
"This will result in a compilation error."
#define PYTHON_TO_CPP_VAR "pythonToCpp"
+#define SMART_POINTER_GETTER "kSmartPointerGetter"
#define CHECKTYPE_REGEX "%CHECKTYPE\\[([^\\[]*)\\]\\("
#define ISCONVERTIBLE_REGEX "%ISCONVERTIBLE\\[([^\\[]*)\\]\\("
@@ -245,6 +246,9 @@ public:
/// Returns true if the class needs to have a getattro function.
bool classNeedsGetattroFunction(const AbstractMetaClass* metaClass);
+ /// Returns true if the class needs to have a setattro function.
+ bool classNeedsSetattroFunction(const AbstractMetaClass *metaClass);
+
/// Returns a list of methods of the given class where each one is part of a different overload with both static and non-static method.
AbstractMetaFunctionList getMethodsWithBothStaticAndNonStaticMethods(const AbstractMetaClass* metaClass);
@@ -273,6 +277,7 @@ public:
const AbstractMetaClass* getProperEnclosingClassForEnum(const AbstractMetaEnum* metaEnum);
QString wrapperName(const AbstractMetaClass* metaClass) const;
+ QString wrapperName(const AbstractMetaType *metaType) const;
static QString fullPythonFunctionName(const AbstractMetaFunction* func);
static QString protectedEnumSurrogateName(const AbstractMetaEnum* metaEnum);
@@ -384,7 +389,7 @@ public:
QString cpythonGetterFunctionName(const AbstractMetaField* metaField);
QString cpythonSetterFunctionName(const AbstractMetaField* metaField);
QString cpythonWrapperCPtr(const AbstractMetaClass* metaClass, QString argName = QLatin1String(PYTHON_SELF_VAR));
- QString cpythonWrapperCPtr(const AbstractMetaType* metaType, QString argName);
+ QString cpythonWrapperCPtr(const AbstractMetaType *metaType, QString argName);
QString cpythonWrapperCPtr(const TypeEntry* type, QString argName);
/// Guesses the scope to where belongs an argument's default value.