aboutsummaryrefslogtreecommitdiffstats
path: root/generators/boostpython/cppgenerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'generators/boostpython/cppgenerator.cpp')
-rw-r--r--generators/boostpython/cppgenerator.cpp1560
1 files changed, 0 insertions, 1560 deletions
diff --git a/generators/boostpython/cppgenerator.cpp b/generators/boostpython/cppgenerator.cpp
deleted file mode 100644
index f144e297a..000000000
--- a/generators/boostpython/cppgenerator.cpp
+++ /dev/null
@@ -1,1560 +0,0 @@
-/*
- * This file is part of the Boost Python Generator project.
- *
- * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Contact: PySide team <contact@pyside.org>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-#include "cppgenerator.h"
-#include <apiextractor/reporthandler.h>
-#include <apiextractor/fileout.h>
-#include <apiextractor/abstractmetalang.h>
-
-#include <QtCore/QDir>
-#include <QtCore/QTextStream>
-#include <QtCore/QVariant>
-#include <QtCore/QRegExp>
-#include <QtCore/QDebug>
-#include <QtCore/QListIterator>
-
-static Indentor INDENT;
-
-// utiliy functions
-inline void writeConversionRule(QTextStream &s, TypeSystem::Language lang, const AbstractMetaFunction *function, const AbstractMetaArgument *arg)
-{
- QString convRule = function->conversionRule(lang, arg->argumentIndex() + 1);
- if (!convRule.isEmpty()) {
- convRule.replace("%in", arg->argumentName());
- convRule.replace("%out", arg->argumentName() + "_out");
- s << convRule;
- }
-}
-
-inline QString getMethodPointerString(const AbstractMetaFunction* func)
-{
- QString className;
- if (!func->declaringClass()->isAbstract())
- className = func->declaringClass()->qualifiedCppName();
- else
- className = func->ownerClass()->qualifiedCppName();
-
- return '&' + className + "::" + func->originalName();
-}
-
-static QString nameForModifiedCtorFunction(const AbstractMetaFunction* func) {
- QString res = func->ownerClass()->name().toLower().replace("::", "_");
- res += "_constructor";
- foreach (AbstractMetaArgument* arg, func->arguments()) {
- res += '_';
- res += arg->type()->name().toLower();
- }
- return res;
-}
-
-static QString createStaticFunctionName(const AbstractMetaFunction* func)
-{
- QString funcName;
- QString originalName(func->name());
-
-
- funcName = func->ownerClass()->name().toLower();
-
- //remove initial 'Q'
- if (funcName.startsWith('q'))
- funcName = funcName.remove(0, 1);
-
- //upercase first letter
- funcName += originalName[0].toUpper() + originalName.mid(1);
-
- return funcName;
-}
-
-QString CppGenerator::fileNameForClass(const AbstractMetaClass* cppClass) const
-{
- return getWrapperName(cppClass) + QLatin1String(".cpp");
-}
-
-QString CppGenerator::getFuncTypedefName(const AbstractMetaFunction* func) const
-{
- return func->name() + QLatin1String("_type");
-}
-
-void CppGenerator::writeConstructorInitialization(QTextStream &s, const AbstractMetaFunction *function)
-{
- QStringList nonOpts;
- QStringList opts;
-
- Options options = Options(SkipName) | SkipDefaultValues;
- foreach (AbstractMetaArgument *arg, function->arguments()) {
- QString argType = argumentString(function, arg, options);
- if (arg->defaultValueExpression().isEmpty())
- nonOpts << argType;
- else
- opts << argType;
- }
-
- bool hasModifications = function->allowThread() || function->hasInjectedCode();
-
- if (hasModifications) {
- s << "\"__init__\", python::make_constructor("
- << nameForModifiedCtorFunction(function);
- } else {
- s << "python::init< ";
-
- if (nonOpts.size() > 0)
- s << nonOpts.join(", ");
-
- if (opts.size() > 0) {
- if (nonOpts.size() > 0)
- s << ", ";
-
- s << "python::optional< " << opts.join(",") << " > ";
- }
-
- s << " > ()";
- }
-
- QString callPolicy = getFunctionCallPolicy(function);
- QString parentType;
- const AbstractMetaClass *cppClass = function->ownerClass();
- uint closePolicy = 0;
- bool hasPolicy = false;
-
- if (
- !hasModifications &&
- (!cppClass->isPolymorphic() || cppClass->hasPrivateDestructor() || cppClass->isNamespace())
- ) {
- closePolicy++;
- hasPolicy = true;
- s << "[ PySide::register_wrapper_object< "
- << function->ownerClass()->qualifiedCppName();
- }
-
- if (callPolicy.isEmpty()) {
- int parentIndex = -1;
- //try find for parent arg to create callPolicy
- foreach (AbstractMetaArgument *arg, function->arguments()) {
- if (arg->argumentName() == "parent") {
- parentIndex = arg->argumentIndex();
- parentType = translateType(arg->type(), function->ownerClass(),
- Options(ExcludeConst) | ExcludeReference).replace("*", "");
- break;
- }
- }
- if (parentIndex != -1) {
- if (!closePolicy)
- s << (hasModifications ? ", " : "[ ");
- else
- s << ", ";
-
- s << "parent_policy_add< " << parentIndex + 2 << ", 1, "
- << parentType << " , " << function->ownerClass()->qualifiedCppName();
-
- hasPolicy = true;
- closePolicy++;
- }
- } else {
- if (!closePolicy)
- s << (hasModifications ? ", " : "[ ");
- else
- s << ", ";
-
- if (callPolicy.endsWith("()"))
- callPolicy = callPolicy.remove(callPolicy.size() - 2, 2);
-
- s << callPolicy;
- hasPolicy = true;
- }
-
- while(closePolicy) {
- s << " > ";
- closePolicy--;
- }
-
- if (hasModifications)
- s << ')';
- else if (hasPolicy)
- s << "() ]";
-}
-
-QString CppGenerator::getFunctionReturnType(const AbstractMetaFunction* func)
-{
- QString modifiedReturnType = QString(func->typeReplaced(0));
-
- return modifiedReturnType.isNull() ? translateType(func->type(), func->implementingClass()) : modifiedReturnType;
-}
-
-QString CppGenerator::writeFunctionCast(QTextStream &s,
- const AbstractMetaFunction* func,
- const QString& castNameSuffix,
- const QString& className)
-{
- QString castName = getFuncTypedefName(func) + castNameSuffix;
- const AbstractMetaClass* cppClass = func->ownerClass();
- bool isWrapped = !func->isVirtual() &&
- (func->hasInjectedCode() || func->isThread() || func->allowThread());
- bool isVirtualMethodDefault = castNameSuffix == "_default";
-
- s << INDENT << "typedef ";
- s << getFunctionReturnType(func);
- s << " (";
- if (cppClass && !func->isStatic() && func->ownerClass() && !isVirtualMethodDefault) {
- if (!isWrapped) {
- // pointer to a class method
- if (!className.isEmpty())
- s << className;
- else if (func->isVirtual() && !func->declaringClass()->isAbstract())
- s << func->declaringClass()->qualifiedCppName();
- else
- s << cppClass->qualifiedCppName();
-
- s << "::";
- }
- }
-
- s << '*' << castName << ") (";
- if (isVirtualMethodDefault) {
- if (func->isConstant())
- s << "const ";
-
- s << func->implementingClass()->qualifiedCppName() << "&";
- if (func->arguments().size() > 0)
- s << ", ";
- }
- Options options = Options(SkipName) | SkipDefaultValues | SkipRemovedArguments;
- if (isWrapped && !func->isStatic())
- options |= WriteSelf;
-
- writeFunctionArguments(s, func, options);
- s << ')';
-
- if (func->isConstant() && !isWrapped && !isVirtualMethodDefault)
- s << " const";
-
- s << ';' << endl;
-
- return castName;
-}
-
-QString CppGenerator::verifyDefaultReturnPolicy(const AbstractMetaFunction *cppFunction, const QString& callPolicy)
-{
- AbstractMetaType *type = cppFunction->type();
-
- //If return type replaced, the return policy need be set manually.
- if (!type || !cppFunction->typeReplaced(0).isEmpty()) {
- return QString();
- }
-
- QString returnPolicy;
-
- if (type->isReference()) {
- QString detail;
- if (type->isConstant()) {
- detail = "copy_const_reference";
- } else {
- detail = "copy_non_const_reference";
- }
-
- returnPolicy = "python::return_value_policy<python::" + detail;
- if (!callPolicy.isEmpty())
- returnPolicy += ", " + callPolicy;
- returnPolicy += " >()";
- } else if (type->isQObject() || type->isObject() || type->isValuePointer()) {
- bool cppOwnership = type->isConstant();
- if (cppFunction->isStatic() || cppOwnership) {
- returnPolicy = QString("python::return_value_policy<PySide::return_ptr_object<")
- + (cppOwnership ? "true" : "false") + QString("> >()");
- } else {
- returnPolicy = QString("PySide::return_object<1, 0, %1, %2 %3 %4 >()")
- .arg(getArgumentType(cppFunction->ownerClass(), cppFunction, -1))
- .arg(getArgumentType(cppFunction->ownerClass(), cppFunction, 0))
- .arg(callPolicy.isEmpty() ? "" : ",")
- .arg(callPolicy);
- }
- } else if (!callPolicy.isEmpty()) {
- returnPolicy = callPolicy + "()";
- }
-
- return returnPolicy;
-}
-
-static int boost_parent_policy_index(int i, const AbstractMetaFunction* func = 0)
-{
- if (func && func->isStatic())
- return i;
-
- if (i == -1)
- return 1;
- else if (i > 0)
- return i + 1;
- else
- return i;
-}
-
-QString CppGenerator::getArgumentType(const AbstractMetaClass *cppClass, const AbstractMetaFunction *func, int idx)
-{
- QString retval;
- if (idx == -1) {
- retval = cppClass->qualifiedCppName();
- } else if (idx == 0 && func->type()) {
- retval = translateType(func->type(), cppClass,
- Options(Generator::ExcludeConst) | Generator::ExcludeReference);
- } else if (idx > 0) {
- retval = argumentString(func, func->arguments()[idx-1],
- Options(SkipDefaultValues) | ExcludeConst |
- ExcludeReference | SkipName);
- }
-
- retval = retval.trimmed();
- if (retval.endsWith('*'))
- retval.chop(1);
- return retval;
-}
-
-QString CppGenerator::getFunctionCallPolicy(const AbstractMetaFunction *func)
-{
- QString callPolicy;
- QStringList callPolicies;
- bool returnChild = false;
- const AbstractMetaClass* cppClass = func->implementingClass();
-
- const int numArgs = func->arguments().count();
-
- if (func->type() && (func->type()->name() == "HANDLE")) {
- return "python::return_value_policy<PySide::return_QHANDLE>()";
- }
-
- for (int i = -1; i <= numArgs; ++i) {
- ArgumentOwner ao = func->argumentOwner(cppClass, i);
- //Parent Policy
- if ((ao.index != -2) && (ao.index != i)) {
- switch (ao.action) {
- case ArgumentOwner::Add:
- if (!i) {
- callPolicy = "return_object<";
- returnChild = true;
- } else {
- callPolicy = "parent_policy_add<";
- }
- break;
- case ArgumentOwner::Remove:
- callPolicy = "parent_policy_remove<";
- break;
- default:
- continue;
- }
-
- callPolicy += QString("%1, %2, %3, %4")
- .arg(boost_parent_policy_index(ao.index, func))
- .arg(boost_parent_policy_index(i, func))
- .arg(getArgumentType(cppClass, func, ao.index))
- .arg(getArgumentType(cppClass, func, i));
-
- callPolicies << callPolicy;
- } else if (i) { //only function args ignore return value
- //Ownership policy
- bool changeOwnership = false;
- bool releaseOwnership = false;
- TypeSystem::Ownership owner = func->ownership(cppClass,
- TypeSystem::TargetLangCode, i);
-
- switch(owner)
- {
- case TypeSystem::CppOwnership:
- releaseOwnership = true;
- case TypeSystem::TargetLangOwnership:
- changeOwnership = true;
- break;
- default:
- changeOwnership = false;
- }
-
- if (changeOwnership)
- {
- QString ownershipPolicy = QString("transfer_ownership<%1, %2, %3")
- .arg(boost_parent_policy_index(i, func))
- .arg(releaseOwnership ? "true" : "false")
- .arg(getArgumentType(cppClass, func, i));
- callPolicies << ownershipPolicy;
- }
- }
- }
-
- if (callPolicies.size() > 0) {
- callPolicy = callPolicies.join(", ");
- for (int i = 0; i < callPolicies.count(); ++i)
- callPolicy += " >";
- }
-
- QString returnPolicy;
-
- //return value
- bool cppOwnership = false;
-
- if (!returnChild) {
- switch (func->ownership(cppClass, TypeSystem::TargetLangCode, 0))
- {
- case TypeSystem::CppOwnership:
- cppOwnership = true;
- case TypeSystem::TargetLangOwnership:
- {
- QString cppOwnershipFlag = (cppOwnership ? "true" : "false");
- returnPolicy = "python::return_value_policy< PySide::return_ptr_object<" + cppOwnershipFlag + "> ";
- if (!callPolicy.isEmpty())
- returnPolicy += ", " + callPolicy;
- returnPolicy += " >()";
- break;
- }
- default:
- returnPolicy = verifyDefaultReturnPolicy(func, callPolicy);
- break;
- }
- }
-
- //return policy
- if (func->shouldReturnThisObject())
- return "python::return_self< " + callPolicy + " >()";
- else if (!returnPolicy.isEmpty())
- return returnPolicy;
- else if (!callPolicy.isEmpty())
- return callPolicy + "()";
-
- return QString();
-}
-
-/*!\internal
- Function used to write the enum boost code on the buffer
- \param s the output buffer
- \param cpp_enum the pointer to metaenum information to be translated to boost
-*/
-void CppGenerator::writeEnum(QTextStream &s,
- const AbstractMetaEnum *cppEnum,
- const QString &nameSpace)
-{
- s << INDENT << "python::enum_<" << nameSpace << cppEnum->name();
- s << ">(\"" << cppEnum->name() << "\")" << endl;
- const AbstractMetaEnumValueList &values = cppEnum->values();
- EnumTypeEntry *ete = cppEnum->typeEntry();
-
- foreach (const AbstractMetaEnumValue* enumValue, values) {
- Indentation indent(INDENT);
- if (ete->isEnumValueRejected(enumValue->name()))
- continue;
-
- s << INDENT << ".value(\"" << enumValue->name() << "\", ";
- s << nameSpace << enumValue->name() << ")" << endl;
- }
-
- //Export values to current scope
- s << INDENT << INDENT << ".export_values()" << endl;
- s << INDENT << ";" << endl << endl;
-
- FlagsTypeEntry* flagsEntry = cppEnum->typeEntry()->flags();
-
- if (flagsEntry) {
- s << INDENT << "PySide::declare_" << (cppEnum->typeEntry()->forceInteger() ? "int_" : "") << "qflags< "
- << flagsEntry->originalName() << " >(\"" << flagsEntry->flagsName() << "\");" << endl;
- }
-
- //register enum in typemanager
- s << INDENT
- << "type_manager::instance().register_native_type<int>(\""
- << nameSpace << cppEnum->name() << "\");\n\n";
-}
-
-void CppGenerator::writeEnums(QTextStream &s, const AbstractMetaClass *cppClass, bool useNamespace)
-{
- AbstractMetaEnumList enums = cppClass->enums();
- if (!enums.size())
- return;
-
- s << INDENT << "// Enums" << endl;
- QString name_space;
- if (useNamespace || !cppClass->isPolymorphic() || cppClass->hasPrivateDestructor())
- name_space = cppClass->qualifiedCppName() + "::";
-
- foreach (AbstractMetaEnum *cpp_enum, enums)
- writeEnum(s, cpp_enum, name_space);
-}
-
-void CppGenerator::writeImplicitlyConversion(QTextStream &s, const AbstractMetaClass *cppClass)
-{
-#if 0
- if (cppClass->isNamespace())
- return;
- s << endl << "// Implicitly conversions" << endl;
- QStringList interfaces = getBaseClasses(cppClass);
-
- if (!interfaces.size()) {
- s << INDENT << "python::implicitly_convertible< " << endl;
- s << INDENT << INDENT << "std::auto_ptr< " << getWrapperName(cppClass->name()) << " >," << endl;
- s << INDENT << INDENT << "std::auto_ptr< " << cppClass->name() << " > >();" << endl;
- } else {
- foreach (QString base_class, interfaces) {
- s << INDENT << "python::implicitly_convertible< " << endl;
- s << INDENT << INDENT << "std::auto_ptr< " << cppClass->name() << " >," << endl;
- s << INDENT << INDENT << "std::auto_ptr< " << base_class << " > >();" << endl;
- }
- }
-#endif
-}
-
-
-void CppGenerator::writeDestructor(QTextStream &s, const AbstractMetaClass *cppClass)
-{
- Indentation indentation(INDENT);
- QString wrapperName = getWrapperName(cppClass);
- s << wrapperName << "::~" << wrapperName << "()" << endl << "{" << endl
- << INDENT << "PySide::qptr_base::invalidate(this);" << endl << "}" << endl;
-}
-
-/*!
- Function used to write the class generated boost code on the buffer
- \param s the output buffer
- \param cppClass the pointer to metaclass information
-*/
-void CppGenerator::generateClass(QTextStream &s, const AbstractMetaClass *cppClass)
-{
- ReportHandler::debugSparse("Generating wrapper implementation for " + cppClass->fullName());
-
- // write license comment
- s << licenseComment() << endl;
-
- QString localStr, globalStr;
- QTextStream includesLocal(&localStr);
- QTextStream includesGlobal(&globalStr);
-
- bool canCreateWrapper = canCreateWrapperFor(cppClass);
-
- QList<Include> includes = cppClass->typeEntry()->extraIncludes();
- qSort(includes.begin(), includes.end());
-
- foreach (Include inc, includes) {
- if (inc.type == Include::IncludePath)
- includesGlobal << inc.toString() << endl;
- else
- includesLocal << inc.toString() << endl;
- }
-
- //workaround to access protected functions
- s << "//workaround to access protected functions" << endl;
- s << "#define protected public" << endl;
-
- s << "//Base Class" << endl;
- if (cppClass->typeEntry()->include().isValid())
- s << cppClass->typeEntry()->include().toString() << endl << endl;
-
- s << "//Extra includes [global]" << endl;
- s << globalStr << endl;
-
- s << "#undef protected" << endl;
- s << "//Base include" << endl;
- s << "#include \"pyside.hpp\"" << endl;
- s << "#include \"" << getWrapperName(cppClass) << ".hpp\"" << endl;
- foreach (AbstractMetaClass* innerClass, cppClass->innerClasses()) {
- if (shouldGenerate(innerClass))
- s << "#include \"" << getWrapperName(innerClass) << ".hpp\"" << endl;
- }
- s << endl << "//Extra includes [local]" << endl;
- s << localStr << endl;
-
- s << endl << "using namespace boost;" << endl;
- s << "using namespace PySide;" << endl;
- s << endl;
-
- if (cppClass->typeEntry()->typeFlags() & ComplexTypeEntry::Deprecated)
- s << "#Deprecated" << endl;
-
- if (canCreateWrapper) {
- writePrelude(s, cppClass);
- if (cppClass->isPolymorphic() && !cppClass->hasPrivateDestructor())
- writeDestructor(s, cppClass);
- }
-
- writeFieldsAccessFunctions(s, cppClass);
-
- //inject code native end
- writeCodeSnips(s, cppClass->typeEntry()->codeSnips(),
- CodeSnip::End, TypeSystem::NativeCode);
-
- writeBoostDeclaration(s, cppClass);
-}
-
-void CppGenerator::writeFieldsAccessFunctions(QTextStream& s, const AbstractMetaClass* cppClass)
-{
- //Fields
- foreach (AbstractMetaField *field, cppClass->fields()) {
- if (field->isPublic()) {
- writeFieldAccess(s, cppClass, field);
- }
- }
-}
-
-void CppGenerator::writePrelude(QTextStream& s, const AbstractMetaClass* cppClass)
-{
- //inject code native beginner
- writeCodeSnips(s, cppClass->typeEntry()->codeSnips(),
- CodeSnip::Beginning, TypeSystem::NativeCode);
-
- foreach (AbstractMetaFunction *func, filterFunctions(cppClass)) {
- if ((func->isPrivate() || func->isModifiedRemoved()) && !func->isAbstract())
- continue;
-
- if (func->isConstructor() && (func->allowThread() || func->hasInjectedCode())) {
- writeModifiedConstructorImpl(s, func);
- } else if (cppClass->isPolymorphic() && !cppClass->hasPrivateDestructor() &&
- func->isConstructor() && !func->isCopyConstructor()) {
- writeConstructorImpl(s, func);
- } else if (func->isVirtual() || func->isAbstract()) {
- writeVirtualMethodImpl(s, func);
- } else if (func->hasInjectedCode() || func->isThread() || func->allowThread()) {
- writeNonVirtualModifiedFunctionImpl(s, func);
- } else if (func->isInGlobalScope() && func->isOperatorOverload()) {
- writeGlobalOperatorOverloadImpl(s, func);
- }
- }
-}
-
-
-void CppGenerator::writeModifiedConstructorImpl ( QTextStream& s, const AbstractMetaFunction* func )
-{
- Indentation indentation(INDENT);
- const AbstractMetaClass* clazz = func->ownerClass();
- s << "static " << clazz->name() << "* " << nameForModifiedCtorFunction(func) << '(';
- writeFunctionArguments(s, func, SkipDefaultValues);
- s << ")\n{" << endl;
-
- s << INDENT << clazz->name() << "* _self = 0;" << endl;
- s << INDENT << '{' << endl;
- {
- Indentation indentation(INDENT);
- if (func->allowThread())
- s << INDENT << "py_allow_threads allow_threads;" << endl;
-
- s << INDENT << "_self = new ";
- writeFunctionCall(s, func);
- s << ';' << endl;
- }
- s << INDENT << '}' << endl;
- writeCodeSnips(s, getCodeSnips(func), CodeSnip::Beginning, TypeSystem::All, func);
- writeCodeSnips(s, getCodeSnips(func), CodeSnip::End, TypeSystem::All, func);
- s << INDENT << "python::object _obj(PySide::ptr(_self));" << endl;
- s << INDENT << "return _self;" << endl;
- s << '}' << endl;
-}
-
-void CppGenerator::writeConstructorImpl(QTextStream& s, const AbstractMetaFunction* func)
-{
- QString wrapperName = getWrapperName(func->ownerClass());
- s << wrapperName << "::" << wrapperName << "(PyObject *py_self" << (func->arguments().size() ? ", " : "");
- writeFunctionArguments(s, func, Options(OriginalTypeDescription) | SkipDefaultValues);
- s << ")" << endl;
- s << INDENT << " : ";
- writeFunctionCall(s, func);
- s << ", wrapper(py_self)" << endl << "{" << endl;
- writeCodeSnips(s, getCodeSnips(func), CodeSnip::Beginning, TypeSystem::All, func);
- writeCodeSnips(s, getCodeSnips(func), CodeSnip::End, TypeSystem::All, func);
- s << '}' << endl << endl;
-}
-
-void CppGenerator::writeVirtualMethodImplHead(QTextStream& s, const AbstractMetaFunction* func)
-{
- Indentation indentation(INDENT);
- s << INDENT << "thread_locker lock;" << endl;
-
- if (func->hasInjectedCode()) {
- writeCodeSnips(s, getCodeSnips(func),
- CodeSnip::Beginning, TypeSystem::NativeCode, func);
- }
-
- s << INDENT << "python::object method = get_override(\"" << func->implementingClass()->name();
- if (func->implementingClass()->typeEntry()->isObject() || func->implementingClass()->typeEntry()->isQObject())
- s << '*';
-
- s << "\", \"" << func->name() << "\");" << endl
- << INDENT << "if (method)" << endl << INDENT << "{" << endl;
-
- {
- Indentation indentation(INDENT);
- s << INDENT << "try {" << endl << INDENT << INDENT;
- if (func->type())
- s << "python::object __result = ";
-
- foreach(AbstractMetaArgument *arg, func->arguments()) {
- writeConversionRule(s, TypeSystem::TargetLangCode, func, arg);
- }
-
- s << INDENT << "method(";
- writeArgumentNames(s, func, Generator::Options(Generator::BoxedPrimitive | Generator::SkipRemovedArguments));
- s << ");" << endl;
-
- QString typeName = getFunctionReturnType(func);
- if (!typeName.isEmpty()) {
-
- CodeSnipList codeSnips = getCodeSnips(func);
- bool hasVirtualBeginningCode = false;
- foreach(CodeSnip cs, codeSnips) {
- if ((cs.position == CodeSnip::Beginning) && (cs.language == TypeSystem::TargetLangCode)) {
- hasVirtualBeginningCode = true;
- break;
- }
- }
-
- if (hasVirtualBeginningCode) {
- writeCodeSnips(s, codeSnips, CodeSnip::Beginning, TypeSystem::TargetLangCode, func);
- } else if (func->type()) {
- s << INDENT << typeName << " __return_value = " << "python::extract<" << typeName << " >(__result);" << endl;
- bool boxedPointer = false;
- if (func->type() && !func->type()->isConstant() &&
- (func->type()->isObject() || func->type()->isQObject())) {
-
- s << INDENT << "PySide::qptr<" << QString(typeName).replace("*", "") << " > __ptr(__result.ptr());" << endl
- << INDENT << "python::incref(__result.ptr());" << endl
- << INDENT << "__ptr.release_ownership();" << endl;
- }
-
- s << INDENT << "return __return_value;" << endl;
- }
- }
-
- s << INDENT << "} catch (boost::python::error_already_set) {" << endl;
- s << INDENT << INDENT << "PyErr_Print();" << endl;
- s << INDENT << INDENT << "throw boost::python::error_already_set();" << endl;
- s << INDENT << "}" << endl;
-
-
- }
- s << INDENT << "}" << endl;
-}
-
-void CppGenerator::writeVirtualMethodImpl(QTextStream& s, const AbstractMetaFunction* func)
-{
- if (func->isModifiedRemoved())
- return;
-
- if (!func->isAbstract() && !func->ownerClass()->hasPrivateDestructor() &&
- func->implementingClass() == func->ownerClass()) {
- writeVirtualDefaultFunction(s, func);
- }
-
-
- QString prefix = getWrapperName(func->ownerClass()) + "::";
- s << functionSignature(func, prefix, "",
- Options(Generator::OriginalTypeDescription) | Generator::SkipDefaultValues | Generator::VirtualCall)
- << endl << "{" << endl;
-
- writeVirtualMethodImplHead(s, func);
-
- if (func->isAbstract())
- writePureVirtualMethodImplFoot(s, func);
- else
- writeVirtualMethodImplFoot(s, func);
-
- s << '}' << endl << endl;
-}
-
-
-void CppGenerator::writePureVirtualMethodImplFoot(QTextStream& s, const AbstractMetaFunction* func)
-{
- Indentation indentation(INDENT);
- s << INDENT << "else" << endl
- << INDENT << "{" << endl;
- {
- Indentation indentation(INDENT);
- s << INDENT << "PyErr_SetString(PyExc_NotImplementedError, \""
- << func->ownerClass()->name() << "." << func->name() << " : "
- << "You need to implement pure virtual functions in python\");" << endl
- << INDENT << "throw python::error_already_set();" << endl;
- }
- s << INDENT << "}" << endl;
-}
-
-void CppGenerator::writeVirtualMethodImplFoot(QTextStream& s, const AbstractMetaFunction* func)
-{
- Indentation indentation(INDENT);
- s << INDENT << "else" << endl << INDENT << "{" << endl;
- {
- Indentation indentation(INDENT);
- QString returnKeyword = func->type() ? QLatin1String("return ") : QString();
-
- if (func->allowThread())
- s << INDENT << "py_allow_threads allow_threads;" << endl;
-
- s << INDENT << returnKeyword << func->implementingClass()->qualifiedCppName() << "::";
- writeFunctionCall(s, func, Generator::VirtualCall);
- s << ';' << endl;
- }
- s << INDENT << '}' << endl;
-}
-
-void CppGenerator::writeVirtualDefaultFunction(QTextStream &s, const AbstractMetaFunction *func)
-{
- Indentation indentation(INDENT);
- QString returnKeyword = func->type() ? QLatin1String("return ") : QString();
- Generator::Options opt = Generator::Options(Generator::SkipDefaultValues);
- QString defaultMethodSignature = signatureForDefaultVirtualMethod(func, getWrapperName(func->ownerClass()) + "::", "_default",
- opt | Generator::SkipRemovedArguments | Generator::VirtualCall);
- s << defaultMethodSignature << endl << '{' << endl;
-
- if (func->allowThread())
- s << INDENT << "py_allow_threads allow_threads;" << endl;
-
- CodeSnipList codeSnips = getCodeSnips(func);
- bool hasVirtualEndCode = false;
- foreach(CodeSnip cs, codeSnips) {
- if ((cs.position == CodeSnip::End) && (cs.language == TypeSystem::TargetLangCode)) {
- hasVirtualEndCode = true;
- break;
- }
- }
-
- foreach(AbstractMetaArgument *arg, func->arguments()) {
- writeConversionRule(s, TypeSystem::NativeCode, func, arg);
- }
-
- if (!hasVirtualEndCode) {
- s << INDENT << returnKeyword << "self." << func->implementingClass()->qualifiedCppName() << "::";
- writeFunctionCall(s, func, opt);
- s << ";" << endl;
- } else {
- writeCodeSnips(s, getCodeSnips(func),
- CodeSnip::End, TypeSystem::TargetLangCode, func);
- }
- s << '}' << endl << endl;
-
-}
-
-
-
-void CppGenerator::writeNonVirtualModifiedFunctionImpl(QTextStream& s, const AbstractMetaFunction* func)
-{
- Indentation indentation(INDENT);
-
- s << "static " << getFunctionReturnType(func) << ' ';
- s << func->ownerClass()->name() << '_' << func->originalName() << "_modified(";
-
- Options options = Options(SkipRemovedArguments) | SkipDefaultValues;
- if (!func->isStatic())
- options |= WriteSelf;
-
- writeFunctionArguments(s, func, options);
- s << ")" << endl << "{" << endl;
-
- if (func->isThread())
- s << INDENT << "thread_locker lock;" << endl;
-
- if (func->allowThread())
- s << INDENT << "py_allow_threads allow_threads;" << endl;
-
- if (getCodeSnips(func).size() > 0) {
- writeCodeSnips(s, getCodeSnips(func), CodeSnip::Beginning, TypeSystem::All, func);
- writeCodeSnips(s, getCodeSnips(func), CodeSnip::End, TypeSystem::All, func);
- } else {
- s << INDENT;
- if (func->type())
- s << "return ";
-
- if (func->isStatic())
- s << func->declaringClass()->name() << "::";
- else
- s << "self.";
-
- writeFunctionCall(s, func);
- s << ";" << endl;
- }
-
- s << '}' << endl << endl;
-}
-
-AbstractMetaFunction* CppGenerator::findMainConstructor(const AbstractMetaClass* clazz)
-{
- foreach (AbstractMetaFunction* func, filterFunctions(clazz)) {
- if (func->isConstructor() &&
- func->isPublic() &&
- !func->isModifiedRemoved() &&
- !func->isPrivate()) {
-
- //do not use copy constructor here
- if (func->isCopyConstructor())
- continue;
- return func;
- }
- }
- return 0;
-}
-
-void CppGenerator::writeGetterFieldFunction(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaField *field)
-{
- s << "static ";
-
- bool pointer = false;
- if (field->type()->isQObject() || field->type()->isObject())
- pointer = true;
-
- if (pointer)
- s << "python::object";
- else
- s << field->type()->cppSignature();
-
- s << " getter_" << cppClass->name() << "_" << field->name() << "(";
-
- if (!field->isStatic())
- s << cppClass->qualifiedCppName() << " &self";
-
- s << ")" << endl << "{" << endl
- << INDENT << "return ";
-
- if (pointer)
- s << "python::object(PySide::ptr(";
-
- if (!field->isStatic())
- s << "self.";
- else
- s << field->enclosingClass()->typeEntry()->qualifiedCppName() << "::";
-
- s << field->name();
-
- if (pointer)
- s << "))";
-
- s << ";" << endl << "}" << endl;
-}
-
-void CppGenerator::writeSetterFieldFunction(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaField *field)
-{
- s << "static void setter_" << cppClass->name() << "_" << field->name() << "(";
-
- if (!field->isStatic())
- s << cppClass->qualifiedCppName() << " &self, ";
-
- s << field->type()->cppSignature() << " _value)" << endl << "{" << endl
- << INDENT;
-
- if (!field->isStatic())
- s << "self.";
- else
- s << field->enclosingClass()->typeEntry()->qualifiedCppName() << "::";
-
- s << field->name() << " = _value;" << endl << "}" << endl;
-}
-
-
-void CppGenerator::writeFieldAccess(QTextStream &s, const AbstractMetaClass *cppClass, const AbstractMetaField *field)
-{
- Indentation indent(INDENT);
-
- writeGetterFieldFunction(s, cppClass, field);
- if (!field->type()->isConstant())
- writeSetterFieldFunction(s, cppClass, field);
-}
-
-
-void CppGenerator::writeHashFunction(QTextStream& s, const AbstractMetaClass* cppClass)
-{
- QString argType;
-
- //WORKAROUND: diferent way to QChar
- if (cppClass->name() == "QChar")
- argType = "QChar";
- else
- argType = "const " + cppClass->name() + "&";
-
- s << "// Hash function" << endl
- << "{" << endl
- << INDENT << INDENT << "typedef uint (*hash_type) ( " << argType << " );"
- << INDENT << INDENT << "python_cls.def(\"__hash__\", hash_type(&"
- << cppClass->typeEntry()->hashFunction() << "));" << endl
- << "}" << endl;
-}
-
-QString CppGenerator::baseClassName(const QString& name)
-{
- QStringList lst = name.split("::");
- return lst.last();
-}
-
-void CppGenerator::writeBoostDeclaration(QTextStream& s, const AbstractMetaClass* cppClass)
-{
- Indentation indent(INDENT);
- QString wrapperName = getWrapperName(cppClass);
-
- s << "void " << wrapperName << "::define_python_class() throw() {" << endl;
-
- const AbstractMetaFunction* mainCtor = 0;
- bool mainCtorHasModifications = false;
- if (!cppClass->isNamespace()) {
- // python_cls declaration
- mainCtor = findMainConstructor(cppClass);
- if (mainCtor)
- mainCtorHasModifications = mainCtor->allowThread() || mainCtor->hasInjectedCode();
-
- s << INDENT;
- if (!cppClass->isPolymorphic() || cppClass->hasPrivateDestructor())
- s << wrapperName << "::";
-
- s << "class_type python_cls(\""
- << baseClassName(cppClass->name()) << "\", ";
-
- if (!mainCtor || mainCtorHasModifications)
- s << "python::no_init";
- else
- writeConstructorInitialization(s, mainCtor);
-
- s << ");" << endl << endl;
- } else {
- QRegExp reg("(?:\\w+::)*(\\w+)");
- reg.indexIn(cppClass->name());
- s << INDENT << "python::class_<Namespace> python_cls(\"" << reg.cap(1) << "\");" << endl;
- }
- // scope declaration
- s << INDENT << "python::scope " << wrapperName << "_scope(python_cls);" << endl;
-
- if (cppClass->templateBaseClass() && cppClass->templateBaseClass()->typeEntry()->isContainer()) {
- s << endl << INDENT << "//Index suite for QContainer" << endl
- << INDENT << "python_cls.def(qcontainer_indexing_suite< " << cppClass->qualifiedCppName() << " >());" << endl << endl;
- }
-
-
- if (cppClass->isPolymorphic() && !cppClass->hasPrivateDestructor() && canCreateWrapperFor(cppClass)) {
- QString heldType = cppClass->typeEntry()->heldTypeValue();
- if (heldType.isEmpty())
- heldType = "PySide::qptr";
-
- s << INDENT << "python::implicitly_convertible< "
- << heldType << "<" << wrapperName << ">, "
- << heldType << "<" << cppClass->qualifiedCppName() << "> >();" << endl;
- }
-
- //Enums
- writeEnums(s, cppClass, cppClass->hasPrivateDestructor() || cppClass->isNamespace());
-
- if (cppClass->innerClasses().count()) {
- s << endl << INDENT << "// Inner classes" << endl;
- foreach (AbstractMetaClass* innerClass, cppClass->innerClasses()) {
- if (!innerClass->typeEntry()->generateCode())
- continue;
- s << INDENT << getWrapperName(innerClass) << "::define_python_class();" << endl;
- }
- }
-
- //Fields
- foreach (AbstractMetaField *field, cppClass->fields()) {
- QString strAccess;
-
- if (field->isPublic()) {
-
- s << INDENT << "python_cls.add_property("
- << "\"" << field->name() << "\""
- << ", getter_" << cppClass->name() << "_" << field->name();
- if (!field->type()->isConstant())
- s << ", setter_" << cppClass->name() << "_" << field->name();
-
- s << ");" << endl;
-
- }
- }
-
- writeCodeSnips(s, cppClass->typeEntry()->codeSnips(),
- CodeSnip::Beginning, TypeSystem::TargetLangCode);
-
- QSet<QString> staticMethods;
- AbstractMetaFunctionList functionList = filterFunctions(cppClass);
-
- if (!cppClass->isNamespace()) {
- //search for all static methods to match with normal functions
- //to rename when match with one member function
- foreach (AbstractMetaFunction *func, functionList) {
- if (func->isStatic() && !func->isOperatorOverload())
- staticMethods << func->name();
- }
- }
-
- foreach (AbstractMetaFunction *func, functionList) {
- if (func->isModifiedRemoved() || func->isPrivate() || func->isSignal())
- continue;
-
- //rename static function when is the same name as member function
- if (!cppClass->isNamespace() && func->isStatic()) {
- QString staticName(createStaticFunctionName(func));
- QSet<QString>::iterator staticFuncInter = staticMethods.find(staticName);
- if (staticFuncInter != staticMethods.end())
- func->setName(staticName);
- } else {
- QSet<QString>::iterator staticFuncInter = staticMethods.find(func->name());
- if (staticFuncInter != staticMethods.end()) {
- staticMethods.erase(staticFuncInter);
- staticMethods << createStaticFunctionName(func);
- }
- }
-
- if (func->isOperatorOverload()) {
- // Do not join the ifs -- isOperatorOverload must be checked alone
- if (func->originalName() == func->name())
- writeOperatorOverload(s, func);
- } else if (func->isConstructor()) {
- //Use same rule as hpp genenrator for copy constructor
- if ((mainCtorHasModifications || func != mainCtor) && !func->isCopyConstructor()) {
- writeConstructor(s, func);
- }
- } else if (!func->isVirtual() &&
- (func->hasInjectedCode() ||
- func->isThread() || func->allowThread())) {
- writeModifiedMethodDef(s, func);
- } else if (func->implementingClass() == func->ownerClass()) {
- writeNormalMethodDef(s, func);
- }
-
- //if is namespace all methothds is stattic
- if (cppClass->isNamespace())
- s << INDENT << "python_cls.staticmethod(\"" << func->name() << "\");" << endl;
- }
-
- //write copy constructor here
- if (isCopyable(cppClass) && !cppClass->isNamespace()) {
- s << INDENT << "python_cls.def(python::init<const ";
- s << cppClass->qualifiedCppName() << "&>());" << endl;
- }
-
- writeCodeSnips(s, cppClass->typeEntry()->codeSnips(),
- CodeSnip::End, TypeSystem::TargetLangCode);
-
- if (!cppClass->isNamespace()) {
- // Static methods
- if (!staticMethods.isEmpty())
- s << INDENT << "// Static methods" << endl;
-
- foreach (QString funcName, staticMethods)
- s << INDENT << "python_cls.staticmethod(\"" << funcName << "\");" << endl;
- }
-
- // qHash usage
- if (!cppClass->typeEntry()->hashFunction().isEmpty())
- writeHashFunction(s, cppClass);
-
- // implicity conversions
- writeImplicitlyConversion(s, cppClass);
-
- // register object/value type
- if (!cppClass->isNamespace()) {
- QString className = cppClass->qualifiedCppName();
- const char* funcName = (cppClass->typeEntry()->isObject() || !isCopyable(cppClass)) ? "object" : "value";
- s << INDENT
- << "type_manager::instance().register_"
- << funcName
- << "_type<" << className << " >(\""
- << cppClass->qualifiedCppName() << (cppClass->typeEntry()->isObject() ? "*" : "") << "\");\n";
- }
- s << '}' << endl;
-}
-
-void CppGenerator::writeConstructor(QTextStream& s, const AbstractMetaFunction* func)
-{
- s << INDENT << "python_cls.def(";
- writeConstructorInitialization(s, func);
- s << ");" << endl;
-}
-
-void CppGenerator::writeFunctionArgsDef(QTextStream &sOut,
- const AbstractMetaFunction *cppFunction)
-{
- bool hasDefaultValue = false;
- int argUsed = 0;
- QString aux;
- QTextStream s(&aux);
-
- foreach (const AbstractMetaArgument *arg, cppFunction->arguments()) {
- if (cppFunction->argumentRemoved(arg->argumentIndex() + 1))
- continue;
-
- if (argUsed > 0)
- s << ", ";
-
- if (!m_disableNamedArgs)
- s << "python::arg(\"" << arg->argumentName() << "\")";
- else
- s << "python::arg(0)";
-
- if (!arg->defaultValueExpression().isEmpty()) {
- QString defaultValue = arg->defaultValueExpression();
- bool isPointer = arg->type()->isObject() ||
- arg->type()->isQObject() ||
- arg->type()->isValuePointer() ||
- arg->type()->isNativePointer();
-
- if (isPointer && defaultValue == "0") {
- defaultValue = "python::object()";
- } else if (arg->type()->isFlags()) {
- defaultValue = " (int) " + defaultValue;
- } else if (arg->type()->isEnum()) {
- QString enumName = arg->type()->minimalSignature();
- QRegExp reg("(.*::)");
- reg.indexIn(enumName);
- if (!defaultValue.startsWith(reg.cap(1)))
- defaultValue = reg.cap(1) + defaultValue;
- }
-
- s << "=" << defaultValue;
- hasDefaultValue = true;
- }
- argUsed++;
- }
-
- if (hasDefaultValue || ((argUsed > 0) && !m_disableNamedArgs))
- sOut << "," << endl << INDENT << INDENT << "(" << aux << ")";
-}
-
-void CppGenerator::writeNormalMethodDef(QTextStream& s, const AbstractMetaFunction* func)
-{
- s << INDENT << '{' << endl;
- {
- Indentation indentation(INDENT);
- QString wrapperClassName = getWrapperName(func->ownerClass());
- bool needDefaultFunction = func->isVirtual() && !func->isAbstract() && !func->ownerClass()->hasPrivateDestructor();
- QString castName;
-
- if (needDefaultFunction)
- castName = writeFunctionCast(s, func, "_default", func->implementingClass()->qualifiedCppName());
- else
- castName = writeFunctionCast(s, func);
-
- s << INDENT << "python_cls.def(\"" << func->name() << "\", ";
-
- if (needDefaultFunction) { // add the default function
- s << castName << "(&" << wrapperClassName << "::" << func->originalName() << "_default)";
- } else {
- if (func->isAbstract())
- s << "python::pure_virtual";
- s << '(' << castName << '(' << getMethodPointerString(func) << "))";
- }
-
- QString functionPolicy = getFunctionCallPolicy(func);
- if (!functionPolicy.isEmpty())
- s << ", " << functionPolicy;
-
- writeFunctionArgsDef(s, func);
- s << ");" << endl;
- }
- s << INDENT << '}' << endl;
-}
-
-void CppGenerator::writeModifiedMethodDef(QTextStream& s, const AbstractMetaFunction* func)
-{
- s << INDENT << '{' << endl;
- {
- Indentation indentation(INDENT);
- QString castName = writeFunctionCast(s, func);
- s << INDENT
- << "python_cls.def(\""
- << func->name() << "\", "
- << castName
- << "(&" << func->implementingClass()->name()
- << "_" << func->originalName()
- << "_modified)";
- QString functionPolicy = getFunctionCallPolicy(func);
- if (!functionPolicy.isEmpty())
- s << ", " << functionPolicy;
-
- writeFunctionArgsDef(s, func);
- s << ");" << endl;
- }
- s << INDENT << '}' << endl;
-}
-
-QString CppGenerator::operatorFunctionName(const AbstractMetaFunction *cppFunction)
-{
- QString funcName = QString("%1_operator_%2_")
- .arg(cppFunction->arguments()[0]->type()->name())
- .arg(cppFunction->arguments()[1]->type()->name());
-
- if (cppFunction->name().contains(">>")) {
- funcName += "rshift";
- } else if (cppFunction->name().contains("<<")) {
- funcName += "lshift";
- } else {
- //TODO: implemente support to others operators
- return QString();
- }
-
- return funcName;
-}
-
-void CppGenerator::writeGlobalOperatorOverloadImpl(QTextStream& s, const AbstractMetaFunction* cppFunction)
-{
- Indentation indent(INDENT);
- QString operatorStr;
-
- if (cppFunction->name().contains(">>")) {
- operatorStr = " >> ";
- } else if (cppFunction->name().contains("<<")) {
- operatorStr = " << ";
- } else {
- //TODO: implemente support to others operators
- return;
- }
-
- QString funcName = operatorFunctionName(cppFunction);
- bool reverse = cppFunction->isReverseOperator();
-
- const AbstractMetaClass *klass = cppFunction->ownerClass();
- s << "python::object " << funcName << "(";
- writeFunctionArguments(s, cppFunction, Options(SkipDefaultValues) | SkipRemovedArguments);
- s << ")" << endl << "{" << endl
- << INDENT << cppFunction->arguments()[reverse]->argumentName()
- << operatorStr << cppFunction->arguments()[!reverse]->argumentName() << ";" << endl
- << INDENT << "return python::object(PySide::ptr(&"
- << cppFunction->arguments()[reverse]->argumentName() << "));" << endl
- << "}" << endl;
-}
-
-void CppGenerator::writeGlobalOperatorOverload(QTextStream &s, const AbstractMetaFunction *cppFunction)
-{
- QString funcName = operatorFunctionName(cppFunction);
- if (funcName.isEmpty())
- return;
-
- bool reverse = cppFunction->isReverseOperator();
- QString operatorStr;
- if (cppFunction->name().contains(">>")) {
- operatorStr = QString("__%1rshift__").arg(reverse ? "r" : "");
- } else if (cppFunction->name().contains("<<")) {
- operatorStr = QString("__%1lshift__").arg(reverse ? "r" : "");
- } else {
- //TODO: implemente support to others operators
- return;
- }
-
- s << INDENT << "python_cls.def(\"" << operatorStr << "\", " << funcName << ");\n";
-}
-
-QString CppGenerator::getOperatorArgumentTypeName(const AbstractMetaFunction *cppFunction, int argumentIndex)
-{
- AbstractMetaType* type = cppFunction->arguments()[argumentIndex]->type();
- if (type->name() == cppFunction->implementingClass()->name())
- return QLatin1String("python::self");
-
- QString typeName = translateType(type, cppFunction->implementingClass(),
- (Option)(ExcludeReference));
- return type->isPrimitive() ? "(" + typeName + ")(0)" : "python::other<" + typeName + " >()";
-}
-
-void CppGenerator::writeOperatorOverload(QTextStream& s, const AbstractMetaFunction* cppFunction)
-{
- static QRegExp operatorRegex("operator(.+)");
-
- if (!operatorRegex.exactMatch(cppFunction->originalName())) {
- qWarning("What kind of operator is that!? %s",
- cppFunction->originalName().toLocal8Bit().data());
- return;
- }
-
- QString op(operatorRegex.cap(1));
- if (op == "=" || op == "[]") {
- // = is handled by type boost and type conversions, [] by someone...
- return;
- }
-
- // no args == member unary operator
- if (!cppFunction->arguments().count()) {
- // check if it is a name instead of an operator symbol
- // this means it is a conversion operator that will be ignored for now
- static QRegExp ConversionOperatorRegex("[A-Za-z]+");
- if (ConversionOperatorRegex.indexIn(op) < 0)
- s << INDENT << "python_cls.def(" << op << "python::self);" << endl;
- return;
- }
-
- //this because global operators use first arg with current class
- if (cppFunction->isInGlobalScope()) {
- writeGlobalOperatorOverload(s, cppFunction);
- return;
- }
-
- QString operand1, operand2;
- if (cppFunction->arguments().count() == 1) {
- operand1 = "python::self";
- operand2 = getOperatorArgumentTypeName(cppFunction, 0);
- } else {
- operand1 = getOperatorArgumentTypeName(cppFunction, 0);
- operand2 = getOperatorArgumentTypeName(cppFunction, 1);
- }
- s << INDENT << "python_cls.def(" << operand1 << ' ' << op << ' ' << operand2 << ");\n";
-}
-
-void CppGenerator::finishGeneration()
-{
- //Generate boost wrapper file
- QString classFiles;
- QTextStream sClassFiles(&classFiles);
- QString classPythonDefines;
- QTextStream sClassPythonDefines(&classPythonDefines);
-
- Indentation indent(INDENT);
-
- foreach (AbstractMetaClass *cls, classes()) {
- if (!shouldGenerate(cls) || cls->enclosingClass())
- continue;
-
- if (m_packageName.isEmpty())
- m_packageName = cls->package();
-
- QString wrapperName = getWrapperName(cls);
- QString boostFilename;
- boostFilename += wrapperName + ".hpp";
- sClassFiles << "#include \"" << boostFilename << "\"" << endl;
-
- QString define_str = wrapperName + "::";
- define_str += "define_python_class();";
-
- sClassPythonDefines << INDENT << define_str << endl;
- }
-
- QString moduleFileName(outputDirectory() + "/" + subDirectoryForPackage(m_packageName));
- moduleFileName += "/" + moduleName().toLower() + "_module_wrapper.cpp";
-
- QFile file(moduleFileName);
- if (file.open(QFile::WriteOnly)) {
- QTextStream s(&file);
-
- // write license comment
- s << licenseComment() << endl;
-
- s << "#include \"converter_register_" << moduleName().toLower();
- s << ".hpp\"" << endl << endl;
-
- s << classFiles << endl;
-
- s << "using namespace boost;" << endl << endl;
- s << "using namespace PySide;" << endl << endl;
-
- s << "// forward decl. for global func. register\n";
- s << "void register_global_functions_" << moduleName().toLower() << "();\n\n";
-
- s << "BOOST_PYTHON_MODULE(" << moduleName() << ")" << endl;
- s << "{" << endl;
-
- foreach (QString requiredModule, TypeDatabase::instance()->requiredTargetImports()) {
- s << INDENT << "if (";
- s << "PyImport_ImportModule(\"" << requiredModule << "\") == NULL) {" << endl;
- s << INDENT << INDENT << "PyErr_SetString(PyExc_ImportError,";
- s << "\"could not import " << requiredModule << "\");" << endl;
- s << INDENT << INDENT << "return;" << endl;
- s << INDENT << "}" << endl;
- }
- s << endl;
-
-
-
- s << INDENT << "register_type_converters_" << moduleName().toLower() << "();" << endl << endl
- << classPythonDefines << endl
- << INDENT << "register_global_functions_" << moduleName().toLower() << "();" << endl
- << INDENT << "//Namespaces" << endl;
-
- s << "}" << endl << endl;
- }
-
- writeGlobalFunctions();
-}
-
-void CppGenerator::writeGlobalFunctions()
-{
- QString fileName = moduleName().toLower() + "_globals_wrapper.cpp";
-
- FileOut fileOut(outputDirectory() + "/" + subDirectoryForPackage(m_packageName) + "/" + fileName);
-
- QSet<QString> includes;
- QString defsStr;
- QTextStream defsStream(&defsStr);
-
- foreach (AbstractMetaFunction* func, globalFunctions()) {
- QString incFile = func->includeFile();
- QRegExp regex("\\b" + moduleName() + "\\b");
- //FIXME: this regex doesn't work with all cases, e.g.:
- // moduleName() = local
- // incFile = /usr/local/include/local
- if (regex.indexIn(incFile) == -1)
- continue;
-
- int idx = incFile.indexOf(moduleName());
- QString cleanPath = QDir::cleanPath(incFile.mid(idx));
- if (!cleanPath.startsWith(moduleName()))
- continue;
-
- includes << cleanPath;
- defsStream << INDENT << "{\n" << INDENT;
- QString castName = writeFunctionCast(defsStream, func);
- defsStream << INDENT << INDENT << "python::def(\"" << func->name();
- defsStream << "\", " << castName << '(' << func->name() << ')';
- if (func->type() && func->type()->isReference())
- defsStream << ", python::return_internal_reference<>()";
- defsStream << ");\n";
- defsStream << INDENT << "}\n";
- }
-
- QTextStream& s = fileOut.stream;
-
- // write license comment
- s << licenseComment() << endl;
-
- s << "#include \"pyside.hpp\"" << endl;
-
- foreach (QString include, includes)
- s << "#include <" << include << ">\n";
-
- s << "using namespace boost;\n\n";
- s << "using namespace PySide;\n\n";
-
- // Add module level code snippets to 'Global' class
- TypeSystemTypeEntry *moduleEntry = dynamic_cast<TypeSystemTypeEntry *>(
- TypeDatabase::instance()->findType(m_packageName));
- QString sEnd;
- QTextStream snipEnd(&sEnd);
- if (moduleEntry && moduleEntry->codeSnips().size() > 0) {
- foreach (CodeSnip snip, moduleEntry->codeSnips()) {
- if (snip.position == CodeSnip().Beginning)
- formatCode(s, snip.code(), INDENT);
- else
- formatCode(snipEnd, snip.code(), INDENT);
- }
- }
-
- s << "\nvoid register_global_functions_" << moduleName().toLower() << "() {\n";
- { //global enums
- QString name_space;
-
- foreach (AbstractMetaEnum *cppEnum, globalEnums()) {
- if (cppEnum)
- writeEnum(s, cppEnum, name_space);
- }
- }
- s << sEnd;
- s << defsStr;
- s << "}\n";
-}
-
-QMap<QString, QString> CppGenerator::options() const
-{
- QMap<QString, QString> res;
- res.insert("disable-named-arg", "Disable Python names arguments.");
- return res;
-}
-
-bool CppGenerator::doSetup(const QMap<QString, QString>& args )
-{
- m_disableNamedArgs = args.contains("disable-named-arg");
- return BoostPythonGenerator::doSetup(args);
-}