mandel@1: /**************************************************************************** mandel@1: ** mandel@1: ** Copyright (C) 1992-2008 Nokia. All rights reserved. mandel@1: ** mandel@1: ** This file is part of Qt Jambi. mandel@1: ** mandel@1: ** * Commercial Usage mandel@1: * Licensees holding valid Qt Commercial licenses may use this file in mandel@1: * accordance with the Qt Commercial License Agreement provided with the mandel@1: * Software or, alternatively, in accordance with the terms contained in mandel@1: * a written agreement between you and Nokia. mandel@1: * mandel@1: * mandel@1: * GNU General Public License Usage mandel@1: * Alternatively, this file may be used under the terms of the GNU mandel@1: * General Public License versions 2.0 or 3.0 as published by the Free mandel@1: * Software Foundation and appearing in the file LICENSE.GPL included in mandel@1: * the packaging of this file. Please review the following information mandel@1: * to ensure GNU General Public Licensing requirements will be met: mandel@1: * http://www.fsf.org/licensing/licenses/info/GPLv2.html and mandel@1: * http://www.gnu.org/copyleft/gpl.html. In addition, as a special mandel@1: * exception, Nokia gives you certain additional rights. These rights mandel@1: * are described in the Nokia Qt GPL Exception version 1.2, included in mandel@1: * the file GPL_EXCEPTION.txt in this package. mandel@1: * mandel@1: * Qt for Windows(R) Licensees mandel@1: * As a special exception, Nokia, as the sole copyright holder for Qt mandel@1: * Designer, grants users of the Qt/Eclipse Integration plug-in the mandel@1: * right for the Qt/Eclipse Integration to link to functionality mandel@1: * provided by Qt Designer and its related libraries. mandel@1: * mandel@1: * mandel@1: * If you are unsure which license is appropriate for your use, please mandel@1: * contact the sales department at qt-sales@nokia.com. mandel@1: mandel@1: ** mandel@1: ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE mandel@1: ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. mandel@1: ** mandel@1: ****************************************************************************/ mandel@1: mandel@1: #include "cppimplgenerator.h" mandel@1: #include "dgenerator.h" mandel@1: #include "reporthandler.h" mandel@1: mandel@1: #include mandel@1: #include mandel@1: #include mandel@1: #include mandel@1: #define VOID_POINTER_ORDINAL 8 mandel@1: mandel@1: static Indentor INDENT; mandel@1: mandel@1: QString jni_signature(const AbstractMetaFunction *function, JNISignatureFormat format) mandel@1: { mandel@1: QString returned = "("; mandel@1: AbstractMetaArgumentList arguments = function->arguments(); mandel@1: foreach (const AbstractMetaArgument *argument, arguments) { mandel@1: if (!function->argumentRemoved(argument->argumentIndex() + 1)) { mandel@1: QString modified_type = function->typeReplaced(argument->argumentIndex()+1); mandel@1: mandel@1: if (modified_type.isEmpty()) mandel@1: returned += jni_signature(argument->type(), format); mandel@1: else mandel@1: returned += jni_signature(modified_type, format); mandel@1: } mandel@1: } mandel@1: mandel@1: returned += ")"; mandel@1: mandel@1: QString modified_type = function->typeReplaced(0); mandel@1: if (modified_type.isEmpty()) mandel@1: returned += jni_signature(function->type(), format); mandel@1: else mandel@1: returned += jni_signature(modified_type, format); mandel@1: mandel@1: return returned; mandel@1: } mandel@1: mandel@1: QString jni_signature(const QString &_full_name, JNISignatureFormat format) mandel@1: { mandel@1: QString signature; mandel@1: QString full_name = _full_name; mandel@1: mandel@1: if (full_name.endsWith("[]")) { mandel@1: full_name.chop(2); mandel@1: signature = "["; mandel@1: } mandel@1: mandel@1: int start = 0, end = -1; mandel@1: while ( (start = full_name.indexOf("<")) >= 0 && (end = full_name.indexOf(">")) >= 0 ) { mandel@1: full_name.remove(start, end - start + 1); mandel@1: } mandel@1: mandel@1: static QHash table; mandel@1: if (table.isEmpty()) { mandel@1: table["boolean"] = "Z"; mandel@1: table["byte"] = "B"; mandel@1: table["char"] = "C"; mandel@1: table["short"] = "S"; mandel@1: table["int"] = "I"; mandel@1: table["long"] = "J"; mandel@1: table["float"] = "F"; mandel@1: table["double"] = "D"; mandel@1: } mandel@1: mandel@1: if (format == Underscores) mandel@1: signature.replace("[", "_3"); mandel@1: mandel@1: if (table.contains(full_name)) { mandel@1: signature += table[full_name]; mandel@1: } else if (format == Underscores) { mandel@1: signature.replace("[", "_3"); mandel@1: signature += "L"; mandel@1: signature += QString(full_name).replace("_", "_1").replace('.', '_').replace("$", "_00024"); mandel@1: signature += "_2"; mandel@1: } else { mandel@1: signature += "L"; mandel@1: signature += QString(full_name).replace('.', '/'); mandel@1: signature += ";"; mandel@1: } mandel@1: mandel@1: return signature; mandel@1: } mandel@1: mandel@1: QString jni_signature(const AbstractMetaType *java_type, JNISignatureFormat format) mandel@1: { mandel@1: if (!java_type) mandel@1: return "V"; mandel@1: mandel@1: if (java_type->isArray()) { mandel@1: return "_3" + jni_signature(java_type->arrayElementType(), format); mandel@1: } else if (java_type->isNativePointer()) { mandel@1: if (format == Underscores) mandel@1: return "Lcom_trolltech_qt_QNativePointer_2"; mandel@1: else mandel@1: return "Lcom/trolltech/qt/QNativePointer;"; mandel@1: } else if (java_type->isIntegerEnum() || java_type->isIntegerFlags() mandel@1: || (format == Underscores && (java_type->isEnum() || java_type->isFlags()))) { mandel@1: return "I"; mandel@1: } else if (java_type->isThread()) { mandel@1: if (format == Underscores) mandel@1: return "Ljava_lang_Thread_2"; mandel@1: else mandel@1: return "Ljava/lang/Thread;"; mandel@1: } mandel@1: mandel@1: mandel@1: mandel@1: QString name = java_type->name(); mandel@1: if (java_type->isObject()) { mandel@1: if (const InterfaceTypeEntry *ie mandel@1: = static_cast(java_type->typeEntry())->designatedInterface()) mandel@1: name = ie->targetLangName(); mandel@1: } else if (java_type->isTargetLangEnum()) { mandel@1: const EnumTypeEntry *et = static_cast(java_type->typeEntry()); mandel@1: name = et->javaQualifier() + "$" + et->targetLangName(); mandel@1: mandel@1: } else if (java_type->isTargetLangFlags()) { mandel@1: const FlagsTypeEntry *ft = static_cast(java_type->typeEntry()); mandel@1: name = ft->originator()->javaQualifier() + "$" + ft->targetLangName(); mandel@1: } mandel@1: mandel@1: return jni_signature( (java_type->package().isEmpty() ? QString() : java_type->package() + ".") + name, format); mandel@1: } mandel@1: mandel@1: static QHash table; mandel@1: QString default_return_statement_qt(const AbstractMetaType *java_type, Generator::Option options = Generator::NoOption) mandel@1: { mandel@1: QString returnStr = ((options & Generator::NoReturnStatement) == 0 ? "return" : ""); mandel@1: if (!java_type) mandel@1: return returnStr; mandel@1: mandel@1: if (table.isEmpty()) { mandel@1: table["bool"] = "false"; mandel@1: table["byte"] = "0"; mandel@1: table["char"] = "0"; mandel@1: table["short"] = "0"; mandel@1: table["int"] = "0"; mandel@1: table["long"] = "0"; mandel@1: table["float"] = "0f"; mandel@1: table["double"] = "0.0"; maxter@382: table["size_t"] = "0"; mandel@1: table["java.lang.Object"] = "0"; mandel@1: } mandel@1: mandel@1: QString signature = table.value(java_type->typeEntry()->targetLangName()); mandel@1: mandel@1: if (!signature.isEmpty()) mandel@1: return returnStr + " " + signature; mandel@1: mandel@1: Q_ASSERT(!java_type->isPrimitive()); maxter@382: mandel@1: if (java_type->isJObjectWrapper()) mandel@1: return returnStr + " JObjectWrapper()"; mandel@1: if (java_type->isVariant()) mandel@1: return returnStr + " QVariant()"; mandel@1: if (java_type->isTargetLangString()) mandel@1: return returnStr + " QString()"; mandel@1: if (java_type->isTargetLangChar()) mandel@1: return returnStr + " QChar()"; mandel@1: else if (java_type->isEnum()) mandel@1: return returnStr + " " + java_type->typeEntry()->name() + "(0)"; mandel@1: else if (java_type->isContainer() && ((ContainerTypeEntry *)java_type->typeEntry())->type() == ContainerTypeEntry::StringListContainer) mandel@1: return returnStr + " " + java_type->typeEntry()->name() + "()"; mandel@1: else if (java_type->isValue() || java_type->isContainer()) mandel@1: return returnStr + " " + java_type->cppSignature() + "()"; mandel@1: else mandel@1: return returnStr + " 0"; mandel@1: } mandel@1: mandel@1: QString default_return_statement_java(const AbstractMetaType *java_type) mandel@1: { mandel@1: if (!java_type) mandel@1: return "return"; mandel@1: if (java_type->isArray()) mandel@1: return "return null"; mandel@1: mandel@1: if (table.isEmpty()) { mandel@1: table["boolean"] = "false"; mandel@1: table["byte"] = "0"; mandel@1: table["char"] = "0"; mandel@1: table["short"] = "0"; mandel@1: table["int"] = "0"; mandel@1: table["long"] = "0"; mandel@1: table["float"] = "0f"; mandel@1: table["double"] = "0.0"; mandel@1: table["java.lang.Object"] = "0"; mandel@1: } mandel@1: mandel@1: QString signature = table.value(java_type->typeEntry()->targetLangName()); mandel@1: if (!signature.isEmpty()) mandel@1: return "return " + signature; mandel@1: mandel@1: Q_ASSERT(!java_type->isPrimitive()); mandel@1: return "return 0"; mandel@1: } mandel@1: mandel@1: /* Used to decide how which of the Call[Xxx]Method functions to call mandel@1: */ mandel@1: QByteArray jniTypeName(const QString &name) { mandel@1: static QHash table; mandel@1: if (table.isEmpty()) { mandel@1: table["jboolean"] = "Boolean"; mandel@1: table["jbyte"] = "Byte"; mandel@1: table["jchar"] = "Char"; mandel@1: table["jshort"] = "Short"; mandel@1: table["jint"] = "Int"; mandel@1: table["jlong"] = "Long"; mandel@1: table["jfloat"] = "Float"; mandel@1: table["jdouble"] = "Double"; mandel@1: table["jobject"] = "Object"; mandel@1: } mandel@1: mandel@1: return table[name]; mandel@1: } mandel@1: mandel@1: QByteArray jniName(const QString &name) { mandel@1: TypeEntry *entry = TypeDatabase::instance()->findType(name); mandel@1: if (entry) mandel@1: return entry->name().toLatin1(); mandel@1: else mandel@1: return "void *"; mandel@1: } mandel@1: mandel@1: QString CppImplGenerator::jniReturnName(const AbstractMetaFunction *java_function, uint options, bool d_export) mandel@1: { eldar@20: AbstractMetaType *f_type = java_function->type(); eldar@20: eldar@20: QString return_type = translateType(f_type, EnumAsInts, d_export); mandel@1: QString new_return_type = java_function->typeReplaced(0); mandel@1: if (!new_return_type.isEmpty()) { eldar@20: if(f_type && f_type->isPrimitive()) { eldar@20: if (d_export) eldar@20: return_type = new_return_type; eldar@20: } else eldar@20: return_type = jniName(new_return_type); mandel@1: } mandel@1: mandel@1: // qtd mandel@1: if (f_type) { eldar@81: if (f_type->name() == "QModelIndex" || f_type->typeEntry()->isStructInD()) mandel@1: return_type = "void"; mandel@1: else if (f_type->isObject() || f_type->isReference() || f_type->isValue() || f_type->isQObject()) mandel@1: return_type = "void*"; mandel@1: if (f_type->isVariant()) mandel@1: return_type = "void*"; mandel@1: } mandel@1: mandel@1: if (options & CppImplGenerator::ExternC && java_function->isConstructor()) mandel@1: return_type = "void*"; mandel@1: if (options & CppImplGenerator::ExternC && f_type) mandel@1: if (f_type->isTargetLangString() || f_type->typeEntry()->isContainer()) mandel@1: return_type = "void"; mandel@1: // qtd end mandel@1: mandel@1: return return_type; mandel@1: } mandel@1: mandel@1: QString CppImplGenerator::jniReturnType(const AbstractMetaType *f_type, uint options) mandel@1: { mandel@1: QString return_type = translateType(f_type, EnumAsInts); mandel@1: mandel@1: // qtd mandel@1: if (f_type) { mandel@1: if (f_type->typeEntry()->isStructInD()) mandel@1: return_type = f_type->typeEntry()->qualifiedCppName(); mandel@1: else if (f_type->isObject() || f_type->isReference() || f_type->isValue() || f_type->isQObject()) mandel@1: return_type = "void*"; mandel@1: if (f_type->isVariant()) mandel@1: return_type = "void*"; mandel@1: } mandel@1: mandel@1: if (options & CppImplGenerator::ExternC && f_type) mandel@1: if (f_type->isTargetLangString()) mandel@1: return_type = "void"; mandel@1: // qtd end mandel@1: return return_type; mandel@1: } mandel@1: mandel@1: QByteArray jniTypeName(const AbstractMetaType *java_type) mandel@1: { mandel@1: if (!java_type) { mandel@1: return "Void"; mandel@1: } else if (java_type->isTargetLangChar()) { mandel@1: return "Char"; mandel@1: } else if (java_type->isPrimitive()) { mandel@1: return jniTypeName(java_type->typeEntry()->jniName()); mandel@1: } else if (java_type->isIntegerEnum() || java_type->isIntegerFlags()) { mandel@1: return "Int"; mandel@1: } else { mandel@1: return "Object"; mandel@1: } mandel@1: } mandel@1: mandel@1: QByteArray newXxxArray(const AbstractMetaType *java_type) mandel@1: { mandel@1: return "New" + jniTypeName(java_type) + "Array"; mandel@1: } mandel@1: mandel@1: QByteArray setXxxArrayElement(const AbstractMetaType *java_type) mandel@1: { mandel@1: Q_ASSERT(java_type); mandel@1: return "Set" + jniTypeName(java_type) + "ArrayElement"; mandel@1: } mandel@1: mandel@1: QByteArray getXxxArrayElement(const AbstractMetaType *java_type) mandel@1: { mandel@1: Q_ASSERT(java_type); mandel@1: return "Get" + jniTypeName(java_type) + "ArrayElement"; mandel@1: } mandel@1: mandel@1: QByteArray getXxxArrayRegion(const AbstractMetaType *java_type) mandel@1: { mandel@1: Q_ASSERT(java_type); mandel@1: return "Get" + jniTypeName(java_type) + "ArrayRegion"; mandel@1: } mandel@1: mandel@1: QByteArray setXxxArrayRegion(const AbstractMetaType *java_type) mandel@1: { mandel@1: Q_ASSERT(java_type); mandel@1: return "Set" + jniTypeName(java_type) + "ArrayRegion"; mandel@1: } mandel@1: mandel@1: QByteArray callXxxMethod(const AbstractMetaType *java_type) mandel@1: { mandel@1: return "Call" + jniTypeName(java_type) + "Method"; mandel@1: } mandel@1: mandel@1: QByteArray callXxxMethod(const QString &name) { mandel@1: TypeEntry *entry = TypeDatabase::instance()->findType(name); mandel@1: if (entry && entry->isPrimitive()) mandel@1: return "Call" + jniTypeName(entry->jniName()) + "Method"; mandel@1: else mandel@1: return "CallObjectMethod"; mandel@1: } mandel@1: mandel@1: QString jni_function_signature(QString package, QString class_name, mandel@1: const QString &function_name, mandel@1: const QString &return_type, mandel@1: const QString &mangled_arguments = QString(), mandel@1: uint options = CppImplGenerator::StandardJNISignature) mandel@1: { mandel@1: QString s; mandel@1: mandel@1: if (options & CppImplGenerator::ExternC) maxter@357: s += "QTD_EXTERN QTD_DLL_PUBLIC "; mandel@1: /* qtd mandel@1: if (options & CppImplGenerator::JNIExport) mandel@1: s += "Q_DECL_EXPORT "; mandel@1: */ eldar@270: if (options & CppImplGenerator::ReturnType) eldar@270: s += return_type + " "; eldar@270: else eldar@270: s += "void "; mandel@1: /* qtd mandel@1: if (options & CppImplGenerator::JNIExport) mandel@1: s += "JNICALL QTJAMBI_FUNCTION_PREFIX("; mandel@1: mandel@1: s += "Java_"; mandel@1: mandel@1: s += package.replace(".", "_"); // qtd .replace("_", "_1") mandel@1: s += '_'; mandel@1: s += class_name; // qtd .replace("_", "_1"); mandel@1: s += '_'; mandel@1: */ mandel@1: s += QString(function_name); //.replace("_", "_1"); mandel@1: // s += mangled_arguments; mandel@1: mandel@1: /* qtd mandel@1: if (options & CppImplGenerator::JNIExport) mandel@1: s += ")"; mandel@1: */ mandel@1: return s; mandel@1: } mandel@1: mandel@1: QString CppImplGenerator::fileNameForClass(const AbstractMetaClass *java_class) const mandel@1: { mandel@1: return QString("%1_shell.cpp").arg(java_class->name()); mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeSignalFunction(QTextStream &s, const AbstractMetaFunction *signal, const AbstractMetaClass *cls, mandel@1: int pos) mandel@1: { mandel@1: writeFunctionSignature(s, signal, cls, signalWrapperPrefix(), mandel@1: Option(OriginalName | OriginalTypeDescription), mandel@1: "QtJambi_SignalWrapper_"); mandel@1: s << endl << "{" << endl; mandel@1: { mandel@1: AbstractMetaArgumentList arguments = signal->arguments(); mandel@1: Indentation indent(INDENT); mandel@1: mandel@1: if (arguments.size() > 0) mandel@1: s << INDENT << "jvalue arguments[" << arguments.size() << "];" << endl; mandel@1: else mandel@1: s << INDENT << "jvalue *arguments = 0;" << endl; mandel@1: s << INDENT << "JNIEnv *__jni_env = qtjambi_current_environment();" << endl mandel@1: << INDENT << "__jni_env->PushLocalFrame(100);" << endl; mandel@1: mandel@1: for (int i=0; itype(), mandel@1: argument->indexedName(), mandel@1: "__java_" + argument->indexedName(), mandel@1: signal, mandel@1: argument->argumentIndex() + 1, mandel@1: BoxedPrimitive); mandel@1: s << INDENT << "arguments[" << i << "].l = __java_" << argument->indexedName() << ";" << endl; mandel@1: } mandel@1: s << INDENT << "qtjambi_call_java_signal(__jni_env, m_signals[" << pos << "], arguments);" mandel@1: << endl; mandel@1: mandel@1: s << INDENT << "__jni_env->PopLocalFrame(0);" << endl; mandel@1: mandel@1: if (signal->type() != 0) mandel@1: s << INDENT << default_return_statement_qt(signal->type()) << ";" << endl; mandel@1: } mandel@1: s << "}" << endl << endl; mandel@1: mandel@1: if (signal->implementingClass() == signal->ownerClass()) mandel@1: writeFinalFunction(s, signal, cls); mandel@1: } mandel@1: mandel@1: bool CppImplGenerator::hasCustomDestructor(const AbstractMetaClass *java_class) const mandel@1: { mandel@1: return !java_class->isQObject() && !java_class->typeEntry()->isValue(); mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeInterfaceCasts(QTextStream &s, const AbstractMetaClass *java_class) mandel@1: { mandel@1: // pointers to native interface objects for classes that implement interfaces mandel@1: // initializing mandel@1: AbstractMetaClassList interfaces = java_class->interfaces(); mandel@1: if (!interfaces.isEmpty()) { mandel@1: for (int i=0; i(iface->typeEntry()); eldar@33: QString real_name = ite->origin()->qualifiedCppName(); eldar@33: maxter@357: s << "QTD_EXTERN QTD_DLL_PUBLIC " << real_name << "* qtd_" << java_class->name() << "_cast_to_" << iface->qualifiedCppName() eldar@33: << "(" << java_class->qualifiedCppName() << " *ptr)" << endl << "{" << endl; mandel@1: Indentation indent(INDENT); eldar@33: s << INDENT << "return dynamic_cast<" << real_name << "*>(ptr);" << endl; mandel@1: s << "}" << endl << endl; mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: void CppImplGenerator::write(QTextStream &s, const AbstractMetaClass *java_class) mandel@1: { mandel@1: mandel@1: bool shellClass = java_class->generateShellClass(); mandel@1: mandel@1: // Includes mandel@1: writeExtraIncludes(s, java_class); mandel@1: bool shellInclude = (java_class->generateShellClass() mandel@1: || java_class->queryFunctions(AbstractMetaClass::Signals | AbstractMetaClass::Visible | AbstractMetaClass::NotRemovedFromShell).size() > 0); mandel@1: mandel@1: // need to include QPainter for all widgets... mandel@1: { mandel@1: const AbstractMetaClass *qwidget = java_class; mandel@1: while (qwidget && qwidget->name() != "QWidget") { mandel@1: qwidget = qwidget->baseClass(); mandel@1: } mandel@1: if (qwidget) mandel@1: s << "#include " << endl << endl; mandel@1: } mandel@1: /* mandel@1: #if defined(QTJAMBI_DEBUG_TOOLS) mandel@1: s << "#include " << endl << endl; mandel@1: #endif mandel@1: */ mandel@1: if (shellInclude) mandel@1: s << "#include \"" << java_class->name() << "_shell" << ".h\"" << endl; mandel@1: /* qtd mandel@1: if (java_class->isQObject()) mandel@1: s << "#include " << endl; mandel@1: */ maxter@253: mandel@1: s << "#include " << endl; maxter@253: maxter@355: writeInclude(s, java_class->typeEntry()->include()); maxter@355: mandel@1: s << endl; // qtd mandel@1: s << "#include \"qtd_core.h\"" << endl mandel@1: << "#include \"ArrayOpsPrimitive.h\"" << endl mandel@1: << "#include \"ArrayOps_qt_core.h\"" << endl; mandel@1: mandel@1: // qtd2 hack!! eldar@37: if (java_class->package() == "qt.svg") mandel@1: s << "#include \"ArrayOps_qt_gui.h\"" << endl; mandel@1: eldar@35: QString pkg_name = QString(java_class->package()).replace(".", "_"); eldar@35: s << QString("#include \"ArrayOps_%1.h\"").arg(pkg_name) << endl; eldar@35: mandel@1: s << endl; mandel@1: mandel@1: writeInterfaceCasts(s, java_class); mandel@1: mandel@1: /* qtd2 mandel@1: writeShellSignatures(s, java_class); mandel@1: mandel@1: writeDefaultConstructedValues(s, java_class); mandel@1: mandel@1: if (hasCustomDestructor(java_class)) */ maxter@354: maxter@354: writeFinalDestructor(s, java_class); eldar@105: eldar@288: if (java_class->isQObject()) { maxter@357: writeQObjectEntity(s, java_class); eldar@288: } eldar@105: if (shellClass) { mandel@1: foreach (AbstractMetaFunction *function, java_class->functions()) { mandel@1: if (function->isConstructor() && !function->isPrivate()) mandel@1: writeShellConstructor(s, function); mandel@1: } maxter@355: mandel@1: writeShellDestructor(s, java_class); mandel@1: maxter@253: if (!java_class->isQObject() && java_class->hasVirtualFunctions()) maxter@253: writeQtdEntityFunction(s, java_class); mandel@1: mandel@1: if (java_class->isQObject()) mandel@1: writeQObjectFunctions(s, java_class); mandel@1: mandel@1: // Virtual overrides mandel@1: s << "// Virtual overrides" << endl; mandel@1: AbstractMetaFunctionList virtualFunctions = java_class->virtualFunctions(); mandel@1: for (int pos = 0; posnonVirtualShellFunctions(); mandel@1: for (int i=0; ipublicOverrideFunctions(); mandel@1: foreach (AbstractMetaFunction *function, public_override_functions) { mandel@1: if(notWrappedYet(function)) mandel@1: continue; mandel@1: writePublicFunctionOverride(s, function, java_class); mandel@1: } mandel@1: mandel@1: // Write virtual function overries used to decide on static/virtual calls mandel@1: s << "// Write virtual function overries used to decide on static/virtual calls" << endl; mandel@1: AbstractMetaFunctionList virtual_functions = java_class->virtualOverrideFunctions(); mandel@1: foreach (const AbstractMetaFunction *function, virtual_functions) { mandel@1: if(notWrappedYet(function)) mandel@1: continue; mandel@1: writeVirtualFunctionOverride(s, function, java_class); mandel@1: } mandel@1: } mandel@1: mandel@1: writeExtraFunctions(s, java_class); mandel@1: /* qtd2 mandel@1: writeToStringFunction(s, java_class); mandel@1: mandel@1: if (java_class->hasCloneOperator()) { mandel@1: writeCloneFunction(s, java_class); mandel@1: } eldar@270: */ eldar@270: // Signals emitters eldar@272: AbstractMetaFunctionList signal_functions = signalFunctions(java_class, false); mandel@1: for (int i=0; iisPrivate()) eldar@270: writeFinalFunction(s, signal_functions.at(i), java_class); eldar@270: } mandel@1: s << "// ---externC---" << endl; mandel@1: mandel@1: // Native callbacks (all java functions require native callbacks) mandel@1: AbstractMetaFunctionList class_funcs = java_class->functionsInTargetLang(); mandel@1: foreach (AbstractMetaFunction *function, class_funcs) { mandel@1: if (!function->isEmptyFunction()) mandel@1: writeFinalFunction(s, function, java_class); mandel@1: } mandel@1: s << "// ---externC---end" << endl; mandel@1: mandel@1: mandel@1: class_funcs = java_class->queryFunctions(AbstractMetaClass::NormalFunctions | AbstractMetaClass::AbstractFunctions | AbstractMetaClass::NotRemovedFromTargetLang); mandel@1: foreach (AbstractMetaFunction *function, class_funcs) { mandel@1: if (function->implementingClass() != java_class) { mandel@1: writeFinalFunction(s, function, java_class); mandel@1: } mandel@1: } mandel@1: mandel@1: // Field accessors mandel@1: s << "// Field accessors" << endl; mandel@1: foreach (AbstractMetaField *field, java_class->fields()) { mandel@1: if (field->wasPublic() || (field->wasProtected() && !java_class->isFinal())) mandel@1: writeFieldAccessors(s, field); mandel@1: } mandel@1: /* mandel@1: s << "// writeFromNativeFunction" << endl; mandel@1: writeFromNativeFunction(s, java_class); mandel@1: mandel@1: if (java_class->isQObject()) mandel@1: writeOriginalMetaObjectFunction(s, java_class); mandel@1: mandel@1: if (java_class->typeEntry()->isValue()) mandel@1: writeFromArrayFunction(s, java_class); mandel@1: mandel@1: // generate the __qt_cast_to_Xxx functions mandel@1: if (!java_class->isNamespace() && !java_class->isInterface()) { mandel@1: AbstractMetaClassList interfaces = java_class->interfaces(); mandel@1: foreach (AbstractMetaClass *iface, interfaces) mandel@1: writeInterfaceCastFunction(s, java_class, iface); mandel@1: } mandel@1: mandel@1: writeSignalInitialization(s, java_class); mandel@1: */ mandel@1: // qtd writeJavaLangObjectOverrideFunctions(s, java_class); mandel@1: eldar@292: if (java_class->typeEntry()->isValue()) eldar@292: writeValueFunctions(s, java_class); eldar@292: maxter@253: if (java_class->isQObject()) maxter@253: { maxter@253: s << endl << endl maxter@357: << "QTD_EXTERN QTD_DLL_PUBLIC void* qtd_" << java_class->name() << "_staticMetaObject() {" << endl maxter@253: << " return (void*)&" << java_class->name() << "::staticMetaObject;" << endl maxter@253: << "}" << endl; maxter@253: } maxter@253: eldar@298: if (java_class->typeEntry()->isValue()) eldar@293: { eldar_ins@304: if (!java_class->typeEntry()->hasPrivateCopyConstructor()) // can do a copy if we have a public ctor or don't have any eldar@293: { eldar@298: QString argName = "orig"; eldar@293: s << endl << endl maxter@357: << "QTD_EXTERN QTD_DLL_PUBLIC void qtd_" << java_class->name() << "_placed_copy(void* " eldar@298: << argName << ", void* place) {" << endl eldar@298: << QString(" const %1& __qt_%2 = (const %1& ) *(%1 *)%2;").arg(shellClassName(java_class)).arg(argName) << endl eldar@298: << QString(" %1 *result = new (place) %1 (__qt_%2);").arg(java_class->qualifiedCppName()).arg(argName) << endl; eldar@298: // writeFinalConstructor(s, ctor, "result", "original", "(place)"); eldar@298: s << "}"; eldar@298: eldar@298: s << endl << endl maxter@357: << "QTD_EXTERN QTD_DLL_PUBLIC void* qtd_" << java_class->name() << "_native_copy(void* " << argName << ") {" << endl eldar@298: << QString(" const %1& __qt_%2 = (const %1& ) *(%1 *)%2;").arg(shellClassName(java_class)).arg(argName) << endl eldar@298: << QString(" %1 *result = new %1 (__qt_%2);").arg(java_class->qualifiedCppName()).arg(argName) << endl eldar@298: << " return result;" << endl; eldar@293: s << "}"; eldar@293: } eldar@293: } eldar@293: mandel@1: s << endl << endl; mandel@1: SokoL_SD@238: priGenerator->addSource(java_class->package(), fileNameForClass(java_class)); mandel@1: } mandel@1: eldar@292: void CppImplGenerator::writeValueFunctions(QTextStream &s, const AbstractMetaClass *java_class) eldar@292: { maxter@357: s << QString("QTD_EXTERN QTD_DLL_PUBLIC bool qtd_%1_QTypeInfo_isComplex() { return (bool) QTypeInfo<%2>::isComplex; }\n").arg(java_class->name()).arg(java_class->qualifiedCppName()); maxter@357: s << QString("QTD_EXTERN QTD_DLL_PUBLIC bool qtd_%1_QTypeInfo_isStatic() { return (bool) QTypeInfo<%2>::isStatic; }\n").arg(java_class->name()).arg(java_class->qualifiedCppName()); maxter@357: s << QString("QTD_EXTERN QTD_DLL_PUBLIC bool qtd_%1_QTypeInfo_isLarge() { return (bool) QTypeInfo<%2>::isLarge; }\n").arg(java_class->name()).arg(java_class->qualifiedCppName()); maxter@357: s << QString("QTD_EXTERN QTD_DLL_PUBLIC bool qtd_%1_QTypeInfo_isPointer() { return (bool) QTypeInfo<%2>::isPointer; }\n").arg(java_class->name()).arg(java_class->qualifiedCppName()); maxter@357: s << QString("QTD_EXTERN QTD_DLL_PUBLIC bool qtd_%1_QTypeInfo_isDummy() { return (bool) QTypeInfo<%2>::isDummy; }\n").arg(java_class->name()).arg(java_class->qualifiedCppName()); eldar@292: } eldar@292: maxter@355: void CppImplGenerator::writeVirtualDispatchFunction(QTextStream &s, const AbstractMetaFunction *function, const AbstractMetaClass *java_class, bool d_export) mandel@1: { maxter@357: uint options2 = ReturnType | ExternC; maxter@357: QString return_type = jniReturnName(function, options2); maxter@357: maxter@357: AbstractMetaFunction::Options opts(AbstractMetaFunction::NoExternNamespace | AbstractMetaFunction::DeclaringClass); maxter@357: QString f_name = function->marshalledName(opts) + "_dispatch"; maxter@357: maxter@357: if (d_export) { maxter@357: QString qtdExtern = "extern(C)"; // TODO: should be settable via a generator switch maxter@357: if (cpp_shared) { maxter@357: maxter@357: s << qtdExtern << "{ extern export " << return_type << " function"; maxter@357: writeVirtualDispatchArguments(s, function, d_export); maxter@357: s << " qtd_" << f_name << "; }" << endl; maxter@357: maxter@357: s << qtdExtern << " " << return_type << " qtd_export_" << f_name; maxter@357: writeVirtualDispatchArguments(s, function, d_export); maxter@357: maxter@357: } else { maxter@357: s << qtdExtern << " " << return_type << " qtd_" << f_name; maxter@357: writeVirtualDispatchArguments(s, function, d_export); maxter@357: } maxter@357: } else { maxter@357: QString module = packageToQtModule(java_class->package()); maxter@357: s << "QTD_EXPORT_DECL(" << module << ", " << return_type << ", " << f_name << ", "; maxter@357: writeVirtualDispatchArguments(s, function, d_export); maxter@357: s << ")" << endl; maxter@357: maxter@357: if (function->declaringClass() == java_class) { maxter@357: s << "QTD_EXPORT(" << module << ", " << f_name << ")" << endl; maxter@357: } maxter@357: } mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeShellVirtualFunction(QTextStream &s, const AbstractMetaFunction *function, mandel@1: const AbstractMetaClass *implementor, int id) mandel@1: { mandel@1: // ---------------------------- mandel@1: if(notWrappedYet(function)) mandel@1: return; mandel@1: mandel@1: AbstractMetaType *f_type = function->type(); mandel@1: QString new_return_type = function->typeReplaced(0); mandel@1: bool has_function_type = ((f_type != 0 mandel@1: || !new_return_type.isEmpty()) mandel@1: && new_return_type != "void"); mandel@1: maxter@355: writeVirtualDispatchFunction(s, function, implementor); mandel@1: mandel@1: writeFunctionSignature(s, function, implementor, QString(), OriginalName); mandel@1: mandel@1: s << endl mandel@1: << "{" << endl; mandel@1: mandel@1: Option options = NoOption; mandel@1: mandel@1: Indentation indent(INDENT); mandel@1: //bool static_call = !(options & VirtualCall); mandel@1: //s << "std::cout << \"entering " << function->marshalledName() << " \\n\"; " << endl; mandel@1: mandel@1: if (f_type) { mandel@1: if (f_type->isTargetLangString()) eldar@104: s << INDENT << "DArray ret_str;" << endl; eldar@81: mandel@1: if (f_type->name() == "QModelIndex") mandel@1: s << INDENT << "QModelIndexAccessor __d_return_value;" << endl; eldar@81: else if (f_type->typeEntry()->isStructInD()) eldar@81: s << INDENT << f_type->typeEntry()->qualifiedCppName() << " __d_return_value;" << endl; eldar@81: mandel@1: if (f_type->isContainer()) eldar@298: { eldar@298: if (isNativeContainer(f_type)) eldar@298: { eldar@298: s << INDENT; eldar@298: writeTypeInfo(s, f_type, ForceValueType); eldar@298: s << "__d_return_value;" << endl; eldar@298: } eldar@298: else eldar@298: s << INDENT << "void* __d_return_value;" << endl eldar@298: << INDENT << "size_t __d_return_value_size;" << endl; eldar@298: } mandel@1: } mandel@1: mandel@1: AbstractMetaArgumentList arguments = function->arguments(); mandel@1: foreach (AbstractMetaArgument *argument, arguments) { mandel@1: if (!function->argumentRemoved(argument->argumentIndex()+1)) { eldar@298: AbstractMetaType *atype = argument->type(); eldar@298: if (!atype->isPrimitive() mandel@1: || !function->conversionRule(TypeSystem::NativeCode, argument->argumentIndex()+1).isEmpty()) { eldar@298: if(atype->isContainer()) { mandel@1: QString arg_name = argument->indexedName(); eldar@298: if(!isNativeContainer(atype)) eldar@298: writeQtToJava(s, eldar@298: argument->type(), eldar@298: arg_name, eldar@298: "__d_" + arg_name, eldar@298: function, eldar@298: argument->argumentIndex() + 1, eldar@298: Option(VirtualDispatch)); mandel@1: } mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: if ((options & NoReturnStatement) == 0) mandel@1: s << INDENT; mandel@1: /* qtd if (function->isAbstract() && static_call) { mandel@1: s << default_return_statement_qt(function->type(), options) << ";" << endl; mandel@1: } else */ mandel@1: { mandel@1: if (f_type) { mandel@1: if (f_type->isTargetLangString() || f_type->isContainer()) mandel@1: ; mandel@1: else if ((f_type->isValue() && !f_type->typeEntry()->isStructInD()) || mandel@1: f_type->isVariant() ) mandel@1: s << f_type->name() << " *__qt_return_value = (" << f_type->name() << "*) "; mandel@1: else if (f_type->isObject() || f_type->isQObject()) mandel@1: s << "return (" << f_type->name() <<"*) "; eldar@81: else if (f_type->name() == "QModelIndex" || f_type->typeEntry()->isStructInD()) mandel@1: ; mandel@1: else if ((options & NoReturnStatement) == 0) mandel@1: s << "return "; mandel@1: mandel@1: if (f_type->isEnum() || f_type->isFlags()) mandel@1: s << "(" << f_type->typeEntry()->qualifiedCppName() <<") "; mandel@1: } mandel@1: maxter@357: s << function->marshalledName(AbstractMetaFunction::DeclaringClass) << "_dispatch("; maxter@355: if (implementor->isQObject()) maxter@355: s << "QObjectLink::getLink(this)->dId"; maxter@355: else maxter@355: s << "this->dId"; mandel@1: mandel@1: if (f_type) { mandel@1: if (f_type->isTargetLangString()) eldar@104: s << ", &ret_str"; eldar@81: if (f_type->name() == "QModelIndex" || f_type->typeEntry()->isStructInD()) eldar@298: s << ", &__d_return_value"; // TODO should both be refactored into isNativeType function eldar@298: if (f_type->isContainer()) { eldar@298: if ( ((const ContainerTypeEntry *)f_type->typeEntry())->isQList() ) eldar@298: s << ", &__d_return_value"; eldar@298: else eldar@298: s << ", &__d_return_value, &__d_return_value_size"; eldar@298: } mandel@1: } mandel@1: mandel@1: if (function->arguments().size() > 0) mandel@1: s << ", "; mandel@1: writeFunctionCallArguments(s, function, QString(), Option(options | ForceEnumCast | SkipRemovedArguments | ExcludeConst | VirtualDispatch)); mandel@1: mandel@1: s << ");" << endl; mandel@1: mandel@1: //s << "std::cout << \"leaving " << function->marshalledName() << " \\n\"; " << endl; mandel@1: mandel@1: if (f_type) { mandel@1: if (f_type->name() == "QModelIndex") { mandel@1: s << INDENT << "QModelIndex __qt_return_value = qtd_to_QModelIndex( __d_return_value );" << endl; mandel@1: s << INDENT << "return __qt_return_value;" << endl; eldar@81: } else if (f_type->typeEntry()->isStructInD()) eldar@81: s << INDENT << "return __d_return_value;" << endl; mandel@1: mandel@1: if (f_type->isContainer()) { eldar@298: if (isNativeContainer(f_type)) eldar@298: s << INDENT << "return __d_return_value;" << endl; eldar@298: else eldar@298: { eldar@298: writeJavaToQt(s, f_type, "__qt_return_value", "__d_return_value", eldar@298: function, 0, GlobalRefJObject); eldar@298: s << INDENT << "return __qt_return_value;" << endl; eldar@298: } mandel@1: } mandel@1: mandel@1: if (f_type->isTargetLangString()) eldar@104: s << INDENT << "return " << "QString::fromUtf8((const char*) ret_str.ptr, ret_str.length);" << endl; mandel@1: mandel@1: if ( ( f_type->isValue() && !f_type->typeEntry()->isStructInD() ) || f_type->isVariant() ) mandel@1: s << INDENT << "return " << f_type->name() << "(*__qt_return_value);" << endl; //" __qt_return_value = "; mandel@1: } mandel@1: } mandel@1: mandel@1: s << "}" << endl << endl; mandel@1: // ---------------------------- mandel@1: } mandel@1: maxter@357: void CppImplGenerator::writeInitCallbacks(QTextStream &s, const AbstractMetaClass *java_class) maxter@357: { maxter@361: QString initArgs = "VoidFunc *virts"; maxter@357: if (java_class->name() == "QObject") maxter@361: initArgs += ", VoidFunc *sigs"; maxter@357: maxter@357: s << "QTD_EXTERN QTD_DLL_EXPORT void qtd_" << java_class->name() maxter@357: << QString("_initCallBacks(%1) {").arg(initArgs) << endl; maxter@357: maxter@357: // virtual functions handlers maxter@357: AbstractMetaFunctionList virtualFunctions = java_class->virtualFunctions(); maxter@357: AbstractMetaFunction::Options opts(AbstractMetaFunction::DeclaringClass | AbstractMetaFunction::NoExternNamespace); maxter@357: for (int pos = 0; posdeclaringClass()) { // qtd2 maxter@357: QString mName = function->marshalledName(opts); maxter@357: s << " qtd_" << mName << "_dispatch = " maxter@357: "(qtd_" << mName << "_dispatch_t) virts[" << pos << "];" << endl; maxter@357: } maxter@357: } maxter@357: // D-side signal callbacks maxter@357: if (java_class->name() == "QObject") { maxter@357: s << " qtd_QObject_qt_metacall_dispatch = (QtMetacallCallback)sigs[0];" << endl maxter@357: << " qtd_QObject_metaObject_dispatch = (MetaObjectCallback)sigs[1];" << endl; maxter@357: } maxter@357: s << "}" << endl; maxter@357: } maxter@357: mandel@1: void CppImplGenerator::writeVirtualDispatchArguments(QTextStream &s, const AbstractMetaFunction *d_function, bool d_export) mandel@1: { mandel@1: uint nativeArgCount = 0; mandel@1: AbstractMetaType *ret_type = d_function->type(); mandel@1: maxter@355: s << "(void *dId"; mandel@1: mandel@1: if (ret_type) { eldar@104: if (ret_type->isTargetLangString()) { eldar@104: if (d_export) eldar@104: s << ", string* ret_str"; eldar@104: else eldar@104: s << ", DArray* ret_str"; eldar@104: } mandel@1: if (ret_type->name() == "QModelIndex") mandel@1: s << ", QModelIndexAccessor *__d_return_value"; eldar@81: else if(ret_type->typeEntry()->isStructInD()) eldar@81: s << ", " << ret_type->typeEntry()->qualifiedCppName() << " *__d_return_value"; eldar@81: eldar@298: if (ret_type->isContainer()) { eldar@298: if(isNativeContainer(ret_type)) { eldar@298: if(d_export) eldar@298: s << ", " << DGenerator::translateType(ret_type, d_function->ownerClass(), NoOption) << "* __d_arr"; eldar@298: else eldar@298: s << ", void * __d_arr"; eldar@298: } eldar@298: else eldar@298: s << ", void** __d_arr_ptr, size_t* __d_arr_size"; eldar@298: } mandel@1: } mandel@1: mandel@1: if (d_function->arguments().size() > 0) mandel@1: s << ", "; mandel@1: mandel@1: mandel@1: // the function arguments mandel@1: AbstractMetaArgumentList arguments = d_function->arguments(); mandel@1: foreach (const AbstractMetaArgument *argument, arguments) { mandel@1: if (!d_function->argumentRemoved(argument->argumentIndex() + 1)) { mandel@1: if (nativeArgCount > 0) mandel@1: s << "," << " "; mandel@1: mandel@1: AbstractMetaType *d_type = argument->type(); mandel@1: QString arg_name = argument->indexedName(); mandel@1: mandel@1: if (d_type->name() == "QModelIndex") mandel@1: s << "QModelIndexAccessor" << QString(d_type->actualIndirections(), '*') << " " << arg_name; mandel@1: else if (d_type->isContainer()) { eldar@298: if ( isNativeContainer(d_type) ) eldar@298: s << "void* "; eldar@298: else if (d_export) mandel@1: s << DGenerator::translateType(d_type, d_function->ownerClass(), NoOption) << "* "; eldar@298: else mandel@1: s << "DArray* "; mandel@1: s << arg_name; mandel@1: } else if (d_type->typeEntry()->isStructInD()) mandel@1: s << d_type->typeEntry()->qualifiedCppName() << QString(d_type->actualIndirections(), '*') mandel@1: << " " << arg_name; mandel@1: else if (d_type->isTargetLangString()) { mandel@1: if (d_export) mandel@1: s << "wchar* "; mandel@1: else mandel@1: s << "const unsigned short* "; mandel@1: s << QString("%1, int %1_size").arg(arg_name); mandel@1: } else { mandel@1: if(d_type->isVariant()) mandel@1: s << "void*"; mandel@1: else if (!d_type->hasNativeId()) mandel@1: { mandel@1: const ComplexTypeEntry *ctype = static_cast(d_type->typeEntry()); mandel@1: if(d_type->typeEntry()->isObject() && ctype->isAbstract() && d_export) mandel@1: { mandel@1: QString d_name = d_type->typeEntry()->qualifiedCppName(); mandel@1: s << d_name + "_ConcreteWrapper" + QString(d_type->indirections(),'*'); mandel@1: } mandel@1: else eldar@39: s << translateType(d_type, EnumAsInts, d_export); mandel@1: } mandel@1: else mandel@1: s << "void*"; mandel@1: s << " " << argument->indexedName(); mandel@1: } mandel@1: nativeArgCount++; mandel@1: } mandel@1: } mandel@1: s << ")"; mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeJavaLangObjectOverrideFunctions(QTextStream &s, const AbstractMetaClass *cls) mandel@1: { mandel@1: if (cls->hasHashFunction()) { mandel@1: AbstractMetaFunctionList hashcode_functions = cls->queryFunctionsByName("hashCode"); mandel@1: bool found = false; mandel@1: foreach (const AbstractMetaFunction *function, hashcode_functions) { mandel@1: if (function->actualMinimumArgumentCount() == 0) { mandel@1: found = true; mandel@1: break; mandel@1: } mandel@1: } mandel@1: mandel@1: if (!found) { mandel@1: s << endl mandel@1: << INDENT << jni_function_signature(cls->package(), cls->name(), "__qt_hashCode", "jint") mandel@1: << "(JNIEnv *__jni_env, jobject, jlong __this_nativeId)" << endl mandel@1: << INDENT << "{" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << INDENT << "Q_UNUSED(__jni_env);" << endl mandel@1: << INDENT << cls->qualifiedCppName() << " *__qt_this = (" mandel@1: << cls->qualifiedCppName() << " *) qtjambi_from_jlong(__this_nativeId);" << endl mandel@1: << INDENT << "QTJAMBI_EXCEPTION_CHECK(__jni_env);" << endl mandel@1: << INDENT << "Q_ASSERT(__qt_this);" << endl mandel@1: << INDENT << "return qHash(*__qt_this);" << endl; mandel@1: } mandel@1: s << INDENT << "}" << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: // Qt has a standard toString() conversion in QVariant? mandel@1: QVariant::Type type = QVariant::nameToType(cls->qualifiedCppName().toLatin1()); mandel@1: if (QVariant(type).canConvert(QVariant::String) && !cls->hasToStringCapability()) { mandel@1: AbstractMetaFunctionList tostring_functions = cls->queryFunctionsByName("toString"); mandel@1: bool found = false; mandel@1: foreach (const AbstractMetaFunction *function, tostring_functions) { mandel@1: if (function->actualMinimumArgumentCount() == 0) { mandel@1: found = true; mandel@1: break; mandel@1: } mandel@1: } mandel@1: mandel@1: if (!found) { mandel@1: s << endl mandel@1: << INDENT << jni_function_signature(cls->package(), cls->name(), "__qt_toString", "jstring") mandel@1: << "(JNIEnv *__jni_env, jobject, jlong __this_nativeId)" << endl mandel@1: << INDENT << "{" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << INDENT << cls->qualifiedCppName() << " *__qt_this = (" mandel@1: << cls->qualifiedCppName() << " *) qtjambi_from_jlong(__this_nativeId);" << endl mandel@1: << INDENT << "QTJAMBI_EXCEPTION_CHECK(__jni_env);" << endl mandel@1: << INDENT << "Q_ASSERT(__qt_this);" << endl mandel@1: << INDENT << "return qtjambi_from_qstring(__jni_env, QVariant(*__qt_this).toString());" << endl; mandel@1: } mandel@1: s << INDENT << "}" << endl; mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeExtraFunctions(QTextStream &s, const AbstractMetaClass *java_class) mandel@1: { mandel@1: const ComplexTypeEntry *class_type = java_class->typeEntry(); mandel@1: Q_ASSERT(class_type); mandel@1: mandel@1: CodeSnipList code_snips = class_type->codeSnips(); mandel@1: foreach (const CodeSnip &snip, code_snips) { mandel@1: if (snip.language == TypeSystem::ShellCode || snip.language == TypeSystem::NativeCode) { mandel@1: snip.formattedCode(s, INDENT) << endl; mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeToStringFunction(QTextStream &s, const AbstractMetaClass *java_class) mandel@1: { mandel@1: FunctionModelItem fun = java_class->hasToStringCapability(); mandel@1: bool core = java_class->package() == QLatin1String("qt.core"); mandel@1: bool qevent = false; mandel@1: mandel@1: const AbstractMetaClass *cls = java_class; mandel@1: while (cls) { mandel@1: if (cls->name() == "QEvent") { mandel@1: qevent = true; mandel@1: fun = cls->hasToStringCapability(); mandel@1: break; mandel@1: } mandel@1: cls = cls->baseClass(); mandel@1: } mandel@1: mandel@1: if (!java_class->hasDefaultToStringFunction() && fun && !(qevent && core)) { mandel@1: mandel@1: int indirections = fun->arguments().at(1)->type().indirections(); mandel@1: QString deref = QLatin1String(indirections == 0 ? "*" : ""); mandel@1: mandel@1: s << endl; mandel@1: s << "#include " << endl; mandel@1: s << jni_function_signature(java_class->package(), java_class->name(), "__qt_toString", "jstring") mandel@1: << "(JNIEnv *__jni_env, jobject, jlong __this_nativeId)" << endl mandel@1: << INDENT << "{" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << INDENT << java_class->qualifiedCppName() << " *__qt_this = (" mandel@1: << java_class->qualifiedCppName() << " *) qtjambi_from_jlong(__this_nativeId);" << endl mandel@1: << INDENT << "QTJAMBI_EXCEPTION_CHECK(__jni_env);" << endl mandel@1: << INDENT << "Q_ASSERT(__qt_this);" << endl mandel@1: mandel@1: << INDENT << "QString res;" << endl mandel@1: << INDENT << "QDebug d(&res);" << endl mandel@1: << INDENT << "d << " << deref << "__qt_this;" << endl; mandel@1: s << INDENT << "return qtjambi_from_qstring(__jni_env, res);" << endl; mandel@1: } mandel@1: s << INDENT << "}" << endl << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeCloneFunction(QTextStream &s, const AbstractMetaClass *java_class) mandel@1: { mandel@1: s << endl mandel@1: << jni_function_signature(java_class->package(), java_class->name(), "__qt_clone", "jobject") << endl mandel@1: << "(JNIEnv *__jni_env, jobject, jlong __this_nativeId)" << endl mandel@1: << INDENT << "{" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << INDENT << java_class->qualifiedCppName() << " *__qt_this = (" mandel@1: mandel@1: << java_class->qualifiedCppName() << " *) qtjambi_from_jlong(__this_nativeId);" << endl mandel@1: << INDENT << "QTJAMBI_EXCEPTION_CHECK(__jni_env);" << endl mandel@1: << INDENT << "Q_ASSERT(__qt_this);" << endl mandel@1: << INDENT << java_class->qualifiedCppName() << " *res = __qt_this;" << endl mandel@1: << INDENT << "return qtjambi_from_object(__jni_env, res, \"" << java_class->name() << "\", \"" << java_class->package().replace(".", "/") << "/\", true);" << endl; mandel@1: } mandel@1: s << INDENT << "}" << endl << endl; mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeShellSignatures(QTextStream &s, const AbstractMetaClass *java_class) mandel@1: { mandel@1: bool has_constructors = java_class->hasConstructors(); mandel@1: mandel@1: // Write the function names... mandel@1: if (has_constructors && java_class->hasVirtualFunctions()) { mandel@1: AbstractMetaFunctionList virtual_functions = java_class->virtualFunctions(); mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: mandel@1: int pos = -1; mandel@1: foreach (AbstractMetaFunction *function, virtual_functions) { mandel@1: ++pos; mandel@1: mandel@1: if (pos == 0) mandel@1: s << "static const char *qtjambi_method_names[] = {"; mandel@1: else mandel@1: s << ","; mandel@1: s << endl mandel@1: << "/* " << QString("%1").arg(QString::number(pos), 3) << " */ " mandel@1: << "\"" << function->name() << "\""; mandel@1: } mandel@1: if (pos >= 0) mandel@1: s << endl << "};" << endl << endl; mandel@1: else mandel@1: s << "static const char **qtjambi_method_names = 0;" << endl; mandel@1: } mandel@1: mandel@1: // Write the function signatures mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: mandel@1: int pos = -1; mandel@1: foreach (AbstractMetaFunction *function, virtual_functions) { mandel@1: ++pos; mandel@1: mandel@1: if (pos == 0) mandel@1: s << "static const char *qtjambi_method_signatures[] = {"; mandel@1: else mandel@1: s << ","; mandel@1: s << endl mandel@1: << "/* " << QString("%1").arg(QString::number(pos), 3) << " */ " mandel@1: << "\"" mandel@1: << jni_signature(function, SlashesAndStuff) mandel@1: << "\""; mandel@1: } mandel@1: if (pos >= 0) mandel@1: s << endl << "};" << endl; mandel@1: else mandel@1: s << "static const char **qtjambi_method_signatures = 0;" << endl; mandel@1: s << "static const int qtjambi_method_count = " << QString::number(pos + 1) << ";" << endl mandel@1: << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: if (has_constructors && java_class->hasInconsistentFunctions()) { mandel@1: AbstractMetaFunctionList inconsistents = java_class->cppInconsistentFunctions(); mandel@1: // Write the inconsistent function names... mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << "static const char *qtjambi_inconsistent_names[] = {"; mandel@1: for (int i=0; iname() << "\""; mandel@1: } mandel@1: s << endl << "};" << endl << endl; mandel@1: } mandel@1: mandel@1: // Write the function signatures mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << "static const char *qtjambi_inconsistent_signatures[] = {"; mandel@1: for (int i=0; icppSignalFunctions(); mandel@1: if (signal_functions.size()) { mandel@1: Indentation indent(INDENT); mandel@1: s << "static const char *qtjambi_signal_names[] = {"; mandel@1: for (int i=0; iname(); mandel@1: mandel@1: s << endl << INDENT << "\"" << signalName << "\""; mandel@1: } mandel@1: s << endl << "};" << endl << endl; mandel@1: mandel@1: s << "static const int qtjambi_signal_argumentcounts[] = {"; mandel@1: for (int i=0; iarguments().count(); mandel@1: } mandel@1: s << endl << "};" << endl << endl; mandel@1: s << "static const int qtjambi_signal_count = " << signal_functions.size() << ";" << endl mandel@1: << endl; mandel@1: } mandel@1: } mandel@1: maxter@253: void CppImplGenerator::writeQObjectEntity(QTextStream &s, const AbstractMetaClass *java_class) maxter@253: { maxter@253: QString entityName = java_class->name() + "Entity"; maxter@253: QString className = java_class->name(); maxter@253: maxter@355: s << "class " << entityName << " : public QObject, public QObjectLink" << endl maxter@253: << "{" << endl maxter@253: << "public:" << endl maxter@253: << " Q_OBJECT_CHECK" << endl eldar@288: << "// virtual int qt_metacall(QMetaObject::Call, int, void **);" << endl << endl maxter@253: maxter@355: << " " << entityName << "(QObject *qObject, void *dId) : QObject(), QObjectLink(qObject, dId) {}" << endl maxter@253: << "};" << endl << endl; maxter@253: eldar@288: /* // QObject_Link::qt_metacall() maxter@253: s << "int " << entityName << "::qt_metacall(QMetaObject::Call _c, int _id, void **_a)" << endl maxter@253: << "{" << endl maxter@253: << " _id = QObject::qt_metacall(_c, _id, _a);" << endl maxter@253: << " if (_id < 0 || _c != QMetaObject::InvokeMetaMethod)" << endl maxter@253: << " return _id;" << endl maxter@253: << " emit_callbacks_" << java_class->name() << "[_id](dId, _a);" << endl maxter@253: << " return -1;" << endl maxter@253: << "}" << endl << endl; eldar@288: */ maxter@357: s << "QTD_EXTERN QTD_DLL_PUBLIC void qtd_" << className << "_createEntity(void *nativeId, void* dId)" << endl maxter@253: << "{" << endl maxter@253: << " new " << entityName << "((QObject*)nativeId, dId);" << endl maxter@253: << "}" << endl << endl; maxter@253: } maxter@253: mandel@1: void CppImplGenerator::writeQObjectFunctions(QTextStream &s, const AbstractMetaClass *java_class) mandel@1: { mandel@1: // QObject::metaObject() mandel@1: /* s << "const QMetaObject *" << shellClassName(java_class) << "::metaObject() const" << endl mandel@1: << "{" << endl mandel@1: << " if (m_meta_object == 0) {" << endl mandel@1: << " JNIEnv *__jni_env = qtjambi_current_environment();" << endl mandel@1: << " jobject __obj = m_link != 0 ? m_link->javaObject(__jni_env) : 0;" << endl mandel@1: << " if (__obj == 0) return " << java_class->qualifiedCppName() << "::metaObject();" << endl mandel@1: << " else m_meta_object = qtjambi_metaobject_for_class(__jni_env, __jni_env->GetObjectClass(__obj), " << java_class->qualifiedCppName() << "::metaObject());" << endl; mandel@1: mandel@1: mandel@1: AbstractMetaFunctionList virtualFunctions = java_class->virtualFunctions(); mandel@1: for (int pos=0; posisVirtualSlot()) { mandel@1: QStringList introspectionCompatibleSignatures = virtualFunction->introspectionCompatibleSignatures(); mandel@1: foreach (QString introspectionCompatibleSignature, introspectionCompatibleSignatures) { mandel@1: s << " {" << endl mandel@1: << " int idx = " mandel@1: << java_class->qualifiedCppName() << "::metaObject()->indexOfMethod(\"" mandel@1: << introspectionCompatibleSignature << "\");" << endl; mandel@1: mandel@1: s << " if (idx >= 0) m_map.insert(idx, " << pos << ");" << endl mandel@1: << " }" << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: } mandel@1: mandel@1: s << " }" << endl mandel@1: << " return m_meta_object;" << endl mandel@1: << "}" << endl << endl; mandel@1: mandel@1: // QObject::qt_metacast() mandel@1: s << "void *" << shellClassName(java_class) << "::qt_metacast(const char *_clname)" << endl mandel@1: << "{" << endl mandel@1: << " if (!_clname) return 0;" << endl mandel@1: << " if (!strcmp(_clname, \"" << shellClassName(java_class) << "\"))" << endl mandel@1: << " return static_cast(const_cast<" << shellClassName(java_class) << "*>(this));" << endl mandel@1: << " return " << java_class->qualifiedCppName() << "::qt_metacast(_clname);" << endl mandel@1: << "}" << endl << endl; mandel@1: */ eldar@288: /* mandel@1: s << "int " << shellClassName(java_class) << "::qt_metacall(QMetaObject::Call _c, int _id, void **_a)" << endl eldar@288: << "{" << endl eldar@288: << " _id = " << java_class->qualifiedCppName() << "::qt_metacall(_c, _id, _a);" << endl eldar@105: << " if (_id < 0 || _c != QMetaObject::InvokeMetaMethod)" << endl maxter@253: << " return _id;" << endl maxter@253: << " emit_callbacks_" << java_class->name() << "[_id](this->dId, _a);" << endl eldar@105: << " return -1;" << endl mandel@1: << "}" << endl << endl; eldar@288: */ eldar@288: maxter@357: QString module = packageToQtModule(java_class->package()); maxter@357: maxter@357: s << "QTD_EXPORT_DECL(" << module << ", const QMetaObject*, QObject_metaObject_dispatch, (void *dId))" << endl maxter@357: << "QTD_EXPORT_DECL(" << module << ", int, QObject_qt_metacall_dispatch, (void *dId, QMetaObject::Call _c, int _id, void **_a))" << endl; maxter@357: maxter@357: if (java_class->name() == "QObject") { maxter@357: s << "QTD_EXPORT(" << module << ", QObject_metaObject_dispatch)" << endl maxter@357: << "QTD_EXPORT(" << module << ", QObject_qt_metacall_dispatch)" << endl; maxter@355: } maxter@355: maxter@355: // TODO: QMetaObject should be included in the typesystem eldar_ins@303: s << endl eldar_ins@303: << "const QMetaObject * " << shellClassName(java_class) << "::metaObject() const" << endl eldar_ins@303: << "{" << endl maxter@355: << " void* dId = QObjectLink::getDId(this);" << endl maxter@355: << " if (dId)" << endl maxter@355: << " return qtd_QObject_metaObject_dispatch(dId);" << endl maxter@355: << " else" << endl maxter@355: << " return " << java_class->qualifiedCppName() << "::metaObject();" << endl eldar_ins@303: << "}" << endl << endl eldar_ins@303: << "int " << shellClassName(java_class) << "::qt_metacall(QMetaObject::Call _c, int _id, void **_a)" << endl eldar@288: << "{" << endl maxter@355: << " void* dId = QObjectLink::getDId(this);" << endl maxter@355: << " if (dId)" << endl maxter@355: << " return qtd_QObject_qt_metacall_dispatch(dId, _c, _id, _a);" << endl maxter@355: << " else" << endl maxter@355: << " return " << java_class->qualifiedCppName() << "::qt_metacall(_c, _id, _a);" << endl eldar@288: << "}" << endl << endl eldar@288: eldar@288: << "int " << shellClassName(java_class) << "::__override_qt_metacall(QMetaObject::Call _c, int _id, void **_a)" << endl eldar@288: << "{" << endl eldar@288: << " return " << java_class->qualifiedCppName() << "::qt_metacall(_c, _id, _a);" eldar@288: << "}" << endl << endl eldar@288: maxter@357: << "QTD_EXTERN QTD_DLL_PUBLIC int qtd_" << java_class->name() << "_qt_metacall(void* __this_nativeId, QMetaObject::Call _c, int _id, void **_a)" eldar@288: << "{" << endl eldar@288: << " " << shellClassName(java_class) << " *__qt_this = (" << shellClassName(java_class) << " *) __this_nativeId;" << endl eldar@288: << " return __qt_this->__override_qt_metacall(_c, _id, _a);" << endl eldar@288: << "}" << endl << endl; mandel@1: } mandel@1: eldar@270: void CppImplGenerator::writeSignalEmitter(QTextStream &s, const AbstractMetaClass *d_class, AbstractMetaFunction *function) mandel@1: { eldar@270: Q_ASSERT(d_class); eldar@270: eldar@270: if (function->isModifiedRemoved(TypeSystem::NativeCode)) eldar@270: return; eldar@270: eldar@270: const AbstractMetaClass *cls = d_class ? d_class : function->ownerClass(); eldar@270: eldar@270: QString function_signature = cls->name() + "::" + function->signature(); eldar@270: eldar@270: s << "// " << function_signature << endl; eldar@270: eldar@270: const QString qt_object_name = function->isStatic() ? shellClassName(cls) : "__qt_this"; eldar@270: eldar@270: // we are not wrapping some functions depending on arguments because API is not yet full eldar@270: if (notWrappedYet(function)) eldar@270: return; eldar@270: eldar@270: // function signature... eldar@270: bool callThrough = function->needsCallThrough(); eldar@270: // uint options = m_native_jump_table ? ReturnType | ExternC : StandardJNISignature; eldar@270: writeFunctionName(s, function, cls, ExternC); eldar@270: s << endl; eldar@270: writeFinalFunctionArguments(s, function); eldar@270: s << endl << "{" << endl; mandel@1: Indentation indent(INDENT); mandel@1: eldar@270: writeFinalFunctionSetup(s, function, qt_object_name, cls); eldar@270: eldar@270: s << "void *args[] = {NULL"; eldar@270: // create an array of pointers to args eldar@270: /* AbstractMetaArgumentList arguments = java_function->arguments(); eldar@270: foreach (const AbstractMetaArgument *argument, arguments) { eldar@270: s << ", "; eldar@270: if (!argument->type()->isPrimitive() eldar@270: || !java_function->conversionRule(TypeSystem::NativeCode, argument->argumentIndex() + 1).isEmpty()) { eldar@270: // s << &qt_arg + n mandel@1: } mandel@1: } eldar@270: */ eldar@270: s << endl << "}"; eldar@270: s << endl << endl; mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeShellConstructor(QTextStream &s, const AbstractMetaFunction *java_function) mandel@1: { mandel@1: if (java_function->isModifiedRemoved(TypeSystem::ShellCode)) mandel@1: return; mandel@1: mandel@1: const AbstractMetaClass *cls = java_function->ownerClass(); mandel@1: AbstractMetaArgumentList arguments = java_function->arguments(); mandel@1: mandel@1: writeFunctionSignature(s, java_function, cls); mandel@1: mandel@1: s << endl; mandel@1: s << " : " << cls->qualifiedCppName() << "("; mandel@1: for (int i=0; iindexedName(); mandel@1: if (i != arguments.size() - 1) mandel@1: s << ", "; mandel@1: } mandel@1: s << ")"; maxter@355: if (cls->isQObject()) { maxter@355: s << "," << endl << " QObjectLink(this, d_ptr)"; maxter@355: } maxter@355: else if (cls->isPolymorphic()) maxter@355: s << "," << endl << " QtdObjectLink(d_ptr)"; mandel@1: /* qtd s << " m_meta_object(0)," << endl; mandel@1: s << " m_vtable(0)," << endl mandel@1: << " m_link(0)" << endl; mandel@1: */ mandel@1: s << endl; mandel@1: s << "{" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); maxter@253: mandel@1: writeCodeInjections(s, java_function, cls, CodeSnip::Beginning, TypeSystem::ShellCode); mandel@1: writeCodeInjections(s, java_function, cls, CodeSnip::End, TypeSystem::ShellCode); mandel@1: } mandel@1: s << "}" << endl << endl; mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeShellDestructor(QTextStream &s, const AbstractMetaClass *java_class) mandel@1: { maxter@354: QString className = shellClassName(java_class); maxter@354: s << className << "::~" << className << "() {" << endl; maxter@354: maxter@355: if (java_class->isQObject()) { maxter@355: s << " destroyLink(this);" << endl; maxter@355: } maxter@355: /* maxter@355: else if (java_class->isPolymorphic()) maxter@355: s << " qtd_delete_d_object(dId);" << endl; maxter@355: */ maxter@354: mandel@1: s << "}" << endl << endl; mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeCodeInjections(QTextStream &s, const AbstractMetaFunction *java_function, mandel@1: const AbstractMetaClass *implementor, CodeSnip::Position position, mandel@1: TypeSystem::Language language) mandel@1: { mandel@1: mandel@1: FunctionModificationList mods; mandel@1: const AbstractMetaClass *cls = implementor; mandel@1: while (cls != 0) { mandel@1: mods += java_function->modifications(cls); mandel@1: mandel@1: if (cls == cls->baseClass()) mandel@1: break; mandel@1: cls = cls->baseClass(); mandel@1: } mandel@1: mandel@1: foreach (FunctionModification mod, mods) { mandel@1: if (mod.snips.count() <= 0) mandel@1: continue ; mandel@1: mandel@1: foreach (CodeSnip snip, mod.snips) { mandel@1: if (snip.position != position) mandel@1: continue ; mandel@1: mandel@1: if ((snip.language & language) == false) mandel@1: continue ; mandel@1: mandel@1: if (position == CodeSnip::End) mandel@1: s << endl; mandel@1: mandel@1: QString code; mandel@1: QTextStream tmpStream(&code); mandel@1: snip.formattedCode(tmpStream, INDENT); mandel@1: ArgumentMap map = snip.argumentMap; mandel@1: ArgumentMap::iterator it = map.begin(); mandel@1: for (;it!=map.end();++it) { mandel@1: int pos = it.key() - 1; mandel@1: QString meta_name = it.value(); mandel@1: mandel@1: if (pos >= 0 && pos < java_function->arguments().count()) { mandel@1: code = code.replace(meta_name, java_function->arguments().at(pos)->indexedName()); mandel@1: } else { mandel@1: QString debug = QString("argument map specifies invalid argument index %1" mandel@1: "for function '%2'") mandel@1: .arg(pos + 1).arg(java_function->name()); mandel@1: ReportHandler::warning(debug); mandel@1: } mandel@1: mandel@1: } mandel@1: s << code; mandel@1: if (position == CodeSnip::Beginning) mandel@1: s << endl; mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: static QString function_call_for_ownership(TypeSystem::Ownership owner, const QString &var_name) mandel@1: { mandel@1: if (owner == TypeSystem::CppOwnership) { mandel@1: return "setCppOwnership(__jni_env, " + var_name + ")"; mandel@1: } else if (owner == TypeSystem::TargetLangOwnership) { mandel@1: return "setJavaOwnership(__jni_env, " + var_name + ")"; mandel@1: } else if (owner == TypeSystem::DefaultOwnership) { mandel@1: return "setDefaultOwnership(__jni_env, " + var_name + ")"; mandel@1: } else { mandel@1: Q_ASSERT(false); mandel@1: return "bogus()"; mandel@1: } mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeOwnership(QTextStream &s, mandel@1: const AbstractMetaFunction *java_function, mandel@1: const QString &var_name, mandel@1: int var_index, mandel@1: const AbstractMetaClass *implementor) mandel@1: { mandel@1: TypeSystem::Ownership owner = TypeSystem::InvalidOwnership; mandel@1: const AbstractMetaClass *cls = implementor; mandel@1: while (cls != 0 && owner == TypeSystem::InvalidOwnership) { mandel@1: owner = java_function->ownership(cls, TypeSystem::ShellCode, var_index); mandel@1: cls = cls->baseClass(); mandel@1: } mandel@1: mandel@1: if (owner == TypeSystem::InvalidOwnership) mandel@1: return; mandel@1: mandel@1: if (var_index != -1) { mandel@1: s << INDENT << "if (" << var_name << " != 0) {" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << INDENT << "QtJambiLink *__link = QtJambiLink::findLink(__jni_env, " mandel@1: << var_name << ");" << endl mandel@1: << INDENT << "Q_ASSERT(__link != 0);" << endl; mandel@1: mandel@1: s << INDENT << "__link->" << function_call_for_ownership(owner, var_name) << ";" << endl; mandel@1: } mandel@1: s << INDENT << "}" << endl; mandel@1: } else { mandel@1: s << INDENT << "if (m_link) {" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << INDENT << "m_link->" << function_call_for_ownership(owner, "m_link->javaObject(__jni_env)") << ";" << endl; mandel@1: } mandel@1: s << INDENT << "}" << endl; mandel@1: } mandel@1: mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeShellFunction(QTextStream &s, const AbstractMetaFunction *java_function, mandel@1: const AbstractMetaClass *implementor, int id) mandel@1: { mandel@1: writeFunctionSignature(s, java_function, implementor, QString(), OriginalName); mandel@1: mandel@1: s << endl mandel@1: << "{" << endl; mandel@1: mandel@1: Indentation indent(INDENT); mandel@1: mandel@1: QString java_function_signature = java_function->signature(); mandel@1: /* s << INDENT << "QTJAMBI_DEBUG_TRACE(\"(shell) entering: " << implementor->name() << "::" mandel@1: << java_function_signature << "\");" << endl; mandel@1: */ mandel@1: writeCodeInjections(s, java_function, implementor, CodeSnip::Beginning, TypeSystem::ShellCode); mandel@1: mandel@1: // s << " printf(\"%s : %s\\n\", \"" << java_function->enclosingClass()->name() << "\"" mandel@1: // << ", \"" << java_function->name() << "\");" << endl; mandel@1: mandel@1: if (!java_function->isFinalInCpp() || java_function->isVirtualSlot()) { mandel@1: s << INDENT << "jmethodID method_id = m_vtable->method(" << id << ");" << endl; mandel@1: s << INDENT << "if (method_id) {" << endl; mandel@1: mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << INDENT << "JNIEnv *__jni_env = qtjambi_current_environment();" << endl; mandel@1: mandel@1: // This nasty case comes up when we're shutting down while receiving virtual mandel@1: // calls.. With these checks we safly abort... mandel@1: s << INDENT << "if (!__jni_env) {" << endl mandel@1: << " "; mandel@1: writeBaseClassFunctionCall(s, java_function, implementor); mandel@1: if (!java_function->type()) { mandel@1: s << INDENT << " return;" << endl; mandel@1: } mandel@1: s << INDENT << "}" << endl; mandel@1: mandel@1: // otherwise, continue with the function call... mandel@1: s << INDENT << "__jni_env->PushLocalFrame(100);" << endl; mandel@1: mandel@1: AbstractMetaArgumentList arguments = java_function->arguments(); mandel@1: AbstractMetaArgumentList argumentsToReset; mandel@1: foreach (AbstractMetaArgument *argument, arguments) { mandel@1: if (!java_function->argumentRemoved(argument->argumentIndex()+1)) { mandel@1: if (!argument->type()->isPrimitive() mandel@1: || !java_function->conversionRule(TypeSystem::NativeCode, argument->argumentIndex()+1).isEmpty()) { mandel@1: writeQtToJava(s, mandel@1: argument->type(), mandel@1: argument->indexedName(), mandel@1: "__java_" + argument->indexedName(), mandel@1: java_function, mandel@1: argument->argumentIndex() + 1); mandel@1: } mandel@1: mandel@1: if (java_function->resetObjectAfterUse(argument->argumentIndex()+1)) mandel@1: argumentsToReset.append(argument); mandel@1: } mandel@1: } mandel@1: mandel@1: for (int i=0; iindexedName(), i+1, implementor); mandel@1: mandel@1: mandel@1: AbstractMetaType *function_type = java_function->type(); mandel@1: QString new_return_type = java_function->typeReplaced(0); mandel@1: bool has_function_type = ((function_type != 0 mandel@1: || !new_return_type.isEmpty()) mandel@1: && new_return_type != "void"); mandel@1: mandel@1: s << INDENT; mandel@1: if (has_function_type) { mandel@1: if (new_return_type.isEmpty()) { mandel@1: s << translateType(function_type); mandel@1: } else { mandel@1: s << jniName(new_return_type); mandel@1: } mandel@1: s << " " << "__d_return_value = "; mandel@1: } mandel@1: mandel@1: s << "__jni_env->"; mandel@1: if (new_return_type.isEmpty()) { mandel@1: s << callXxxMethod(java_function->type()); mandel@1: } else if (!has_function_type) { mandel@1: s << "CallVoidMethod"; mandel@1: } else { mandel@1: s << callXxxMethod(new_return_type); mandel@1: } mandel@1: mandel@1: s << "(m_link->javaObject(__jni_env), method_id"; mandel@1: if (arguments.size() > 0) mandel@1: s << ", "; mandel@1: writeFunctionCallArguments(s, java_function, "__java_", Option(NoCasts | SkipRemovedArguments)); mandel@1: s << ");" << endl mandel@1: << INDENT << "qtjambi_exception_check(__jni_env);" << endl; mandel@1: mandel@1: if (has_function_type) { mandel@1: writeJavaToQt(s, function_type, "__qt_return_value", "__d_return_value", mandel@1: java_function, 0, GlobalRefJObject); mandel@1: mandel@1: if (java_function->nullPointersDisabled()) { mandel@1: s << INDENT << "if (__d_return_value == 0) {" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << INDENT << "fprintf(stderr, \"QtJambi: Unexpected null pointer returned from override of '" << java_function->name() << "' in class '%s'\\n\"," << endl mandel@1: << INDENT << " qPrintable(qtjambi_object_class_name(__jni_env, m_link->javaObject(__jni_env))));" << endl; mandel@1: s << INDENT << "__qt_return_value = "; mandel@1: QString defaultValue = java_function->nullPointerDefaultValue(); mandel@1: if (!defaultValue.isEmpty()) mandel@1: s << defaultValue << ";"; mandel@1: else mandel@1: writeBaseClassFunctionCall(s, java_function, implementor, NoReturnStatement); mandel@1: s << endl; mandel@1: } mandel@1: mandel@1: s << INDENT << "}" << endl; mandel@1: } mandel@1: } else if (!java_function->conversionRule(TypeSystem::ShellCode, 0).isEmpty()) { mandel@1: writeConversionRule(s, TypeSystem::ShellCode, java_function, 0, "", ""); mandel@1: } mandel@1: mandel@1: writeOwnership(s, java_function, "this", -1, implementor); mandel@1: writeOwnership(s, java_function, "__d_return_value", 0, implementor); mandel@1: mandel@1: foreach (AbstractMetaArgument *argumentToReset, argumentsToReset) { mandel@1: mandel@1: QString argumentName = "__java_" + argumentToReset->indexedName(); mandel@1: mandel@1: s << INDENT; mandel@1: if (argumentToReset->type()->isContainer()) mandel@1: s << "qtjambi_invalidate_collection("; mandel@1: else mandel@1: s << "qtjambi_invalidate_object("; mandel@1: mandel@1: s << "__jni_env, " << argumentName << ");" << endl; mandel@1: } mandel@1: mandel@1: s << INDENT << "__jni_env->PopLocalFrame(0);" << endl; mandel@1: mandel@1: s << INDENT << "QTJAMBI_DEBUG_TRACE(\"(shell) -> leaving: " << implementor->name() mandel@1: << "::" << java_function_signature << "\");" << endl; mandel@1: mandel@1: if (function_type) mandel@1: s << INDENT << "return __qt_return_value;" << endl; mandel@1: mandel@1: } mandel@1: mandel@1: s << INDENT << "} else {" << endl; mandel@1: mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << INDENT << "QTJAMBI_DEBUG_TRACE(\"(shell) -> super() and leaving: " mandel@1: << implementor->name() << "::" << java_function_signature << "\");" << endl; mandel@1: writeBaseClassFunctionCall(s, java_function, implementor); mandel@1: } mandel@1: mandel@1: mandel@1: s << INDENT << "}" << endl; mandel@1: mandel@1: writeCodeInjections(s, java_function, implementor, CodeSnip::End, TypeSystem::ShellCode); mandel@1: mandel@1: // A little trick to close open painters on a widget mandel@1: if (java_function->name() == "paintEvent") { mandel@1: s << INDENT << "JNIEnv *env = qtjambi_current_environment();" << endl mandel@1: << INDENT << "qtjambi_end_paint(env, m_link->javaObject(env));" << endl; mandel@1: } mandel@1: mandel@1: } else { mandel@1: if(java_function->isRemovedFrom(implementor, TypeSystem::TargetLangCode)){ mandel@1: // Avoid compiler warnings for unused parameters mandel@1: AbstractMetaArgumentList arguments = java_function->arguments(); mandel@1: mandel@1: foreach (const AbstractMetaArgument *argument, arguments) { mandel@1: s << INDENT << "Q_UNUSED(" << argument->indexedName() << ")" << endl; mandel@1: } mandel@1: } mandel@1: writeBaseClassFunctionCall(s, java_function, implementor); mandel@1: writeCodeInjections(s, java_function, implementor, CodeSnip::End, TypeSystem::ShellCode); mandel@1: } mandel@1: mandel@1: s << "}" << endl << endl; mandel@1: mandel@1: } mandel@1: mandel@1: // ### kill implementor mandel@1: mandel@1: void CppImplGenerator::writePublicFunctionOverride(QTextStream &s, mandel@1: const AbstractMetaFunction *java_function, mandel@1: const AbstractMetaClass *implementor) mandel@1: { mandel@1: Q_ASSERT(java_function->originalAttributes() mandel@1: & (AbstractMetaAttributes::Protected mandel@1: | AbstractMetaAttributes::Final)); mandel@1: mandel@1: // The write a public override version of this function to be used by native functions mandel@1: writeFunctionSignature(s, java_function, implementor, "__public_", mandel@1: Option(EnumAsInts | UnderscoreSpaces mandel@1: | (java_function->isAbstract() ? SkipName : NoOption))); mandel@1: s << endl mandel@1: << "{" << endl; mandel@1: Indentation indent(INDENT); mandel@1: writeBaseClassFunctionCall(s, java_function, implementor); mandel@1: s << "}" << endl << endl; mandel@1: } mandel@1: maxter@253: void CppImplGenerator::writeQtdEntityFunction(QTextStream &s, const AbstractMetaClass *java_class) maxter@253: { maxter@357: s << "QTD_EXTERN QTD_DLL_PUBLIC void *__" << java_class->name() << "_entity(void *q_ptr)" << endl; maxter@253: s << "{" << endl; maxter@253: { maxter@253: Indentation indent(INDENT); maxter@355: s << INDENT << "QtdObjectLink* a = dynamic_cast((" << java_class->qualifiedCppName() << "*)q_ptr);" << endl maxter@253: << INDENT << "if (a != NULL)" << endl maxter@253: << INDENT << " return a->dId;" << endl maxter@253: << INDENT << "else" << endl maxter@253: << INDENT << " return NULL;" << endl; maxter@253: } maxter@253: s << "}" << endl << endl; maxter@253: } mandel@1: mandel@1: void CppImplGenerator::writeVirtualFunctionOverride(QTextStream &s, mandel@1: const AbstractMetaFunction *java_function, mandel@1: const AbstractMetaClass *implementor) mandel@1: { mandel@1: Q_ASSERT(!java_function->isFinalInCpp()); mandel@1: mandel@1: Option options = Option(EnumAsInts | UnderscoreSpaces); mandel@1: mandel@1: // The write a public override version of this function to be used by native functions mandel@1: writeFunctionSignature(s, java_function, implementor, "__override_", mandel@1: options, eldar@21: QString(), // the class prefix eldar@21: QStringList() << "bool static_call"); mandel@1: s << endl mandel@1: << "{" << endl; mandel@1: Indentation indent(INDENT); eldar@21: s << INDENT << "if (static_call) {" << endl; mandel@1: { eldar@21: Indentation indent(INDENT); mandel@1: writeBaseClassFunctionCall(s, java_function, implementor); eldar@21: } mandel@1: s << INDENT << "} else {" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: writeBaseClassFunctionCall(s, java_function, implementor, VirtualCall); mandel@1: } mandel@1: eldar@21: s << INDENT << "}" << endl; mandel@1: s << "}" << endl << endl; mandel@1: } mandel@1: mandel@1: mandel@1: void CppImplGenerator::writeBaseClassFunctionCall(QTextStream &s, mandel@1: const AbstractMetaFunction *java_function, mandel@1: const AbstractMetaClass *, mandel@1: Option options) mandel@1: { mandel@1: bool static_call = !(options & VirtualCall); mandel@1: if ((options & NoReturnStatement) == 0) mandel@1: s << INDENT; mandel@1: if (java_function->isAbstract() && static_call) { mandel@1: s << default_return_statement_qt(java_function->type(), options) << ";" << endl; mandel@1: } else { mandel@1: if (java_function->type() && (options & NoReturnStatement) == 0) mandel@1: s << "return "; mandel@1: if (static_call) { mandel@1: const AbstractMetaClass *implementor = java_function->implementingClass(); mandel@1: if (java_function->isInterfaceFunction()) mandel@1: implementor = java_function->interfaceClass()->primaryInterfaceImplementor(); mandel@1: s << implementor->qualifiedCppName() << "::"; mandel@1: } mandel@1: s << java_function->originalName() << "("; mandel@1: writeFunctionCallArguments(s, java_function, QString(), Option(options | ForceEnumCast)); mandel@1: s << ");" << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: mandel@1: void CppImplGenerator::writeFunctionName(QTextStream &s, mandel@1: const AbstractMetaFunction *java_function, mandel@1: const AbstractMetaClass *java_class, mandel@1: uint options) mandel@1: { mandel@1: const AbstractMetaClass *cls = java_class ? java_class : java_function->ownerClass(); mandel@1: AbstractMetaArgumentList arguments = java_function->arguments(); mandel@1: mandel@1: // Function signature mandel@1: QString return_type = jniReturnName(java_function, options); mandel@1: mandel@1: QString function_name; mandel@1: mandel@1: bool callThrough = java_function->needsCallThrough(); mandel@1: /* qtd if (!callThrough) mandel@1: function_name = java_function->name(); mandel@1: else */ mandel@1: function_name = java_function->marshalledName(); mandel@1: mandel@1: QString args = "__"; mandel@1: mandel@1: if (callThrough && !java_function->isStatic() && !java_function->isConstructor()) mandel@1: args += "J"; mandel@1: mandel@1: if (!arguments.isEmpty()) { mandel@1: foreach (const AbstractMetaArgument *argument, arguments) { mandel@1: if (!java_function->argumentRemoved(argument->argumentIndex() + 1)) { mandel@1: if (!argument->type()->hasNativeId()) { mandel@1: QString modified_type = java_function->typeReplaced(argument->argumentIndex()+1); mandel@1: if (modified_type.isEmpty()) mandel@1: args += jni_signature(argument->type(), Underscores); mandel@1: else mandel@1: args += jni_signature(modified_type, Underscores); mandel@1: } else { mandel@1: args += "J"; mandel@1: } mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: s << jni_function_signature(cls->package(), cls->name(), function_name, mandel@1: return_type, args, options); mandel@1: mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeFinalFunctionArguments(QTextStream &s, const AbstractMetaFunction *java_function, bool d_export) mandel@1: { mandel@1: bool callThrough = java_function->needsCallThrough(); mandel@1: s << "("; mandel@1: /* qtd mandel@1: << "JNIEnv *__jni_env," << endl; mandel@1: if (!java_function->isConstructor()) { mandel@1: if (java_function->isStatic()) mandel@1: s << " jclass"; mandel@1: else mandel@1: s << " jobject"; mandel@1: } else mandel@1: s << " jobject " << java_object_name; mandel@1: */ mandel@1: uint nativeArgCount = 0; mandel@1: const AbstractMetaClass *cls = java_function->ownerClass(); mandel@1: if (java_function->isConstructor() && maxter@355: ( cls->isPolymorphic() mandel@1: || cls->typeEntry()->isObject() ) ) mandel@1: { mandel@1: s << "void *d_ptr"; mandel@1: nativeArgCount++; mandel@1: } mandel@1: mandel@1: // passing pointer to C++ object maxter@355: bool hasNativeId = callThrough && !java_function->isStatic() && !java_function->isConstructor(); mandel@1: if (hasNativeId) { mandel@1: if (nativeArgCount > 0) mandel@1: s << "," << endl << " "; mandel@1: /* qtd << "," << endl */ s << "void* __this_nativeId"; mandel@1: nativeArgCount++; mandel@1: } mandel@1: mandel@1: AbstractMetaType *f_type = java_function->type(); mandel@1: mandel@1: // return values as strings, arrays or QModelIndex'es we return as arguments mandel@1: bool return_arg = false; mandel@1: if (f_type) { mandel@1: if (f_type->isTargetLangString() || mandel@1: f_type->isContainer() || eldar@81: f_type->name() == "QModelIndex" || eldar@81: f_type->typeEntry()->isStructInD()) mandel@1: return_arg = true; mandel@1: mandel@1: if (return_arg && nativeArgCount > 0) mandel@1: s << "," << endl << " "; mandel@1: mandel@1: if (f_type->isTargetLangString() || f_type->isContainer()) mandel@1: s << "void*"; mandel@1: else if (f_type->name() == "QModelIndex") mandel@1: s << "QModelIndexAccessor*"; eldar@81: else if (f_type->typeEntry()->isStructInD()) eldar@81: s << f_type->typeEntry()->qualifiedCppName() << " *"; mandel@1: mandel@1: if(return_arg) { mandel@1: s << " __d_return_value"; mandel@1: nativeArgCount++; mandel@1: } mandel@1: } mandel@1: mandel@1: // the function arguments mandel@1: AbstractMetaArgumentList arguments = java_function->arguments(); mandel@1: foreach (const AbstractMetaArgument *argument, arguments) { mandel@1: if (!java_function->argumentRemoved(argument->argumentIndex() + 1)) { mandel@1: AbstractMetaType *d_type = argument->type(); mandel@1: const TypeEntry *te = d_type->typeEntry(); mandel@1: mandel@1: QString arg_name = argument->indexedName(); mandel@1: mandel@1: if (nativeArgCount > 0) mandel@1: s << "," << endl << " "; eldar@81: eldar@81: // if QString argument we have to pass DArray eldar@35: if ((te && te->qualifiedCppName() == "QString") || d_type->isTargetLangString()) { eldar@35: if (d_export) eldar@35: s << "string " << arg_name; eldar@35: else eldar@35: s << "DArray " << arg_name; eldar@35: } else if (d_type->isContainer()) { mandel@1: const ContainerTypeEntry *cte = mandel@1: static_cast(te); eldar@298: if(cte->isQList()) eldar@298: s << "void* " << arg_name; eldar@298: else if(isLinearContainer(cte)) eldar@298: s << "DArray* " << arg_name; mandel@1: } else { mandel@1: if (!d_type->hasNativeId()) { mandel@1: if(d_type->isVariant()) { mandel@1: if (d_export) s << "void*"; mandel@1: else s << "QVariant*"; mandel@1: } else mandel@1: s << translateType(argument->type(), EnumAsInts, d_export); mandel@1: } eldar@188: else if (d_type->name() == "QModelIndex") { eldar@188: if(d_export && dVersion == 2 && d_type->isConstant()) eldar@188: s << "const(QModelIndexAccessor)"; eldar@188: else eldar@188: s << "QModelIndexAccessor"; eldar@188: } else if (te->isStructInD()) mandel@1: s << te->qualifiedCppName(); mandel@1: else mandel@1: s << "void*"; mandel@1: mandel@1: s << " " << arg_name; mandel@1: } mandel@1: nativeArgCount++; mandel@1: } mandel@1: } mandel@1: s << ")"; mandel@1: } mandel@1: mandel@1: mandel@1: /*! mandel@1: Generates type conversion from Java -> Qt for all the arguments mandel@1: that are to be to be passed to the function mandel@1: */ mandel@1: void CppImplGenerator::writeFinalFunctionSetup(QTextStream &s, const AbstractMetaFunction *java_function, mandel@1: const QString &qt_object_name, mandel@1: const AbstractMetaClass *cls) mandel@1: { mandel@1: mandel@1: // Translate each of the function arguments into qt types mandel@1: AbstractMetaArgumentList arguments = java_function->arguments(); mandel@1: foreach (const AbstractMetaArgument *argument, arguments) { mandel@1: if (!argument->type()->isPrimitive() mandel@1: || !java_function->conversionRule(TypeSystem::NativeCode, argument->argumentIndex() + 1).isEmpty()) { mandel@1: writeJavaToQt(s, mandel@1: argument->type(), mandel@1: "__qt_" + argument->indexedName(), mandel@1: argument->indexedName(), mandel@1: java_function, mandel@1: argument->argumentIndex() + 1, mandel@1: Option(UseNativeIds | EnumAsInts)); mandel@1: } mandel@1: } mandel@1: mandel@1: // Extract the qt equivalent to the this pointer and name it "qt_object_name" mandel@1: if (!java_function->isStatic() && !java_function->isConstructor()) { mandel@1: // qtd2 QString className = java_function->isFinalOverload() ? cls->name() : shellClassName(cls); mandel@1: QString className = java_function->isFinalOverload() ? cls->name() : shellClassName(cls); mandel@1: s << INDENT mandel@1: << className << " *" << qt_object_name mandel@1: << " = (" << className << " *) __this_nativeId;" mandel@1: << endl; mandel@1: // << INDENT << "QTJAMBI_EXCEPTION_CHECK(__jni_env);" << endl mandel@1: // qtd << INDENT << "Q_ASSERT(" << qt_object_name << ");" << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeFinalFunction(QTextStream &s, const AbstractMetaFunction *java_function, mandel@1: const AbstractMetaClass *java_class) mandel@1: { mandel@1: Q_ASSERT(java_class); mandel@1: mandel@1: if (java_function->isModifiedRemoved(TypeSystem::NativeCode)) mandel@1: return; mandel@1: mandel@1: const AbstractMetaClass *cls = java_class ? java_class : java_function->ownerClass(); mandel@1: mandel@1: QString java_function_signature = cls->name() + "::" + java_function->signature(); mandel@1: mandel@1: s << "// " << java_function_signature << endl; mandel@1: mandel@1: const AbstractMetaType *function_type = java_function->type(); mandel@1: QString new_return_type = java_function->typeReplaced(0); mandel@1: bool has_function_type = new_return_type != "void" mandel@1: && (!new_return_type.isEmpty() || function_type != 0) mandel@1: && java_function->argumentReplaced(0).isEmpty(); mandel@1: mandel@1: const QString qt_object_name = java_function->isStatic() ? shellClassName(cls) : "__qt_this"; mandel@1: const QString java_object_name = java_function->isStatic() ? "__jni_class" : "__jni_object"; mandel@1: mandel@1: // we are not wrapping some functions depending on arguments because API is not yet full mandel@1: if (notWrappedYet(java_function)) mandel@1: return; mandel@1: mandel@1: // function signature... mandel@1: bool callThrough = java_function->needsCallThrough(); mandel@1: uint options = m_native_jump_table ? ReturnType | ExternC : StandardJNISignature; mandel@1: writeFunctionName(s, java_function, cls, options); mandel@1: s << endl; mandel@1: writeFinalFunctionArguments(s, java_function); mandel@1: s << endl << "{" << endl; mandel@1: Indentation indent(INDENT); mandel@1: mandel@1: // qtd2 s << INDENT << "QTJAMBI_DEBUG_TRACE(\"(native) entering: " << java_function_signature << "\");" << endl; mandel@1: bool hasNativeId = (callThrough && !java_function->isStatic() && !java_function->isConstructor()); mandel@1: /* if (hasNativeId) mandel@1: s << INDENT << "Q_UNUSED(__this_nativeId)" << endl; mandel@1: // Avoid compiler warnings when the variables are unused mandel@1: { mandel@1: s << INDENT << "Q_UNUSED(__jni_env)" << endl; mandel@1: mandel@1: if (java_function->isConstructor()) mandel@1: s << INDENT << "Q_UNUSED(" << java_object_name << ")" << endl; mandel@1: mandel@1: bool hasNativeId = (callThrough && !java_function->isStatic() && !java_function->isConstructor()); mandel@1: if (hasNativeId) mandel@1: s << INDENT << "Q_UNUSED(__this_nativeId)" << endl; mandel@1: } mandel@1: */ mandel@1: mandel@1: if (cls->isFinal() && (!java_function->isAbstract() || !java_function->isFinalInTargetLang()) && !java_function->wasPublic()) { mandel@1: QString debug = QString("protected function '%1' in final class '%2'") mandel@1: .arg(java_function->signature()).arg(java_class->name()); mandel@1: ReportHandler::warning(debug); mandel@1: // Avoid compiler warnings for unused parameters mandel@1: AbstractMetaArgumentList arguments = java_function->arguments(); mandel@1: mandel@1: foreach (const AbstractMetaArgument *argument, arguments) { mandel@1: s << INDENT << "Q_UNUSED(" << argument->indexedName() << ")" << endl; mandel@1: } mandel@1: s << INDENT << default_return_statement_qt(java_function->type()) << ""; mandel@1: } else { mandel@1: writeFinalFunctionSetup(s, java_function, qt_object_name, cls); mandel@1: mandel@1: writeCodeInjections(s, java_function, java_function->implementingClass(), CodeSnip::Beginning, TypeSystem::NativeCode); mandel@1: mandel@1: if (java_function->isConstructor()) { mandel@1: writeFinalConstructor(s, java_function, qt_object_name, java_object_name); mandel@1: } else { mandel@1: mandel@1: QString function_prefix = ""; mandel@1: QStringList extra_param; mandel@1: Option option = NoOption; mandel@1: mandel@1: bool hasShell = cls->generateShellClass(); mandel@1: mandel@1: if (java_function->isFinalOverload()) { mandel@1: // no prefix mandel@1: } else if (java_function->isFinalInCpp() && !java_function->wasPublic() && hasShell) { mandel@1: function_prefix = "__public_"; mandel@1: } else if (!java_function->isFinalInCpp() && !java_function->isStatic() && hasShell) { mandel@1: function_prefix = "__override_"; eldar@21: extra_param.append("__do_static_call"); mandel@1: s << INDENT maxter@355: << "bool __do_static_call = " maxter@355: << "dynamic_cast((" << java_class->polymorphicBase()->qualifiedCppName() << "*)__this_nativeId) != NULL;" << endl; eldar@21: } else { mandel@1: option = OriginalName; mandel@1: } mandel@1: mandel@1: // Call the Qt function on the java object mandel@1: s << " "; mandel@1: if (has_function_type) { mandel@1: const QString qt_return_value = "__qt_return_value"; mandel@1: const QString java_return_value = "__d_return_value"; mandel@1: if (function_type) { mandel@1: writeTypeInfo(s, function_type, EnumAsInts); mandel@1: s << " " << qt_return_value mandel@1: << " = "; mandel@1: } mandel@1: mandel@1: writeFunctionCall(s, qt_object_name, java_function, function_prefix, option, mandel@1: extra_param); mandel@1: s << endl; mandel@1: eldar@104: writeRefArguments(s, java_function); eldar@104: mandel@1: writeQtToJava(s, function_type, qt_return_value, java_return_value, mandel@1: java_function, 0, EnumAsInts); mandel@1: mandel@1: // qtd s << INDENT << "QTJAMBI_DEBUG_TRACE(\"(native) -> leaving: " mandel@1: // << java_function_signature << "\");"; mandel@1: mandel@1: if (function_type && function_type->name() != "QModelIndex") { mandel@1: if(function_type->typeEntry()->isStructInD()) eldar@81: ; //s << endl << INDENT << "return " << qt_return_value << ";"; mandel@1: else if (!function_type->isTargetLangString() && !function_type->isContainer()) mandel@1: s << endl << INDENT << "return " << java_return_value << ";"; mandel@1: } mandel@1: mandel@1: } else { mandel@1: writeFunctionCall(s, qt_object_name, java_function, function_prefix, option, mandel@1: extra_param); eldar@104: writeRefArguments(s, java_function); mandel@1: } mandel@1: } mandel@1: } mandel@1: if(!java_function->argumentReplaced(0).isEmpty()) { mandel@1: s << INDENT << "return 0;" << endl; mandel@1: } mandel@1: mandel@1: s << endl << "}"; mandel@1: s << endl << endl; mandel@1: } mandel@1: eldar@33: void CppImplGenerator::writeRefArguments(QTextStream &s, const AbstractMetaFunction *java_function) eldar@33: { eldar@33: AbstractMetaArgumentList arguments = java_function->arguments(); eldar@33: foreach (const AbstractMetaArgument *argument, arguments) { eldar@33: AbstractMetaType *d_type = argument->type(); eldar@33: const TypeEntry *te = d_type->typeEntry(); eldar@33: if ((te && d_type->isNativePointer() && te->name() == "QString")) maxter@253: s << QString(" qtd_toUtf8(__qt_%1.utf16(), __qt_%1.size(), &%1);").arg(argument->indexedName()) << endl; eldar@33: } eldar@33: } eldar@33: mandel@1: void CppImplGenerator::writeAssignment(QTextStream &s, const QString &destName, const QString &srcName, mandel@1: const AbstractMetaType *java_type) mandel@1: { mandel@1: if (java_type->isArray()) { mandel@1: for (int i=0; iarrayElementCount(); ++i) { mandel@1: writeAssignment(s, destName + "[" + QString::number(i) + "]", mandel@1: srcName + "[" + QString::number(i) + "]", java_type->arrayElementType()); mandel@1: } mandel@1: } else { mandel@1: s << INDENT << destName << " = " << srcName << ";" << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeFieldAccessors(QTextStream &s, const AbstractMetaField *java_field) mandel@1: { mandel@1: Q_ASSERT(java_field); mandel@1: Q_ASSERT(java_field->isPublic() || java_field->isProtected()); mandel@1: mandel@1: const AbstractMetaFunction *setter = java_field->setter(); mandel@1: const AbstractMetaFunction *getter = java_field->getter(); mandel@1: mandel@1: const AbstractMetaClass *cls = java_field->enclosingClass(); mandel@1: FieldModification mod = cls->typeEntry()->fieldModification(java_field->name()); mandel@1: mandel@1: if(notWrappedYet(getter)) mandel@1: return; mandel@1: mandel@1: if (mod.isReadable()) { mandel@1: // Getter mandel@1: if (getter->wasProtected()) { mandel@1: writeFunctionSignature(s, getter, getter->ownerClass()); mandel@1: s << endl mandel@1: << "{" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << INDENT << "return " << java_field->name() << ";" << endl; mandel@1: } mandel@1: s << "}" << endl << endl; mandel@1: } mandel@1: mandel@1: mandel@1: writeFunctionName(s, getter, getter->ownerClass()); mandel@1: s << endl; mandel@1: writeFinalFunctionArguments(s, getter); mandel@1: s << "{" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: mandel@1: mandel@1: writeFinalFunctionSetup(s, getter, "__qt_object", getter->ownerClass()); mandel@1: mandel@1: const QString java_return_value = "__d_return_value"; mandel@1: QString qt_return_value; mandel@1: if (setter->isStatic()) mandel@1: qt_return_value = shellClassName(setter->ownerClass()) + "::"; mandel@1: else mandel@1: qt_return_value = "__qt_object->"; mandel@1: mandel@1: mandel@1: // To avoid "taking address of tmp" mandel@1: s << INDENT; mandel@1: writeTypeInfo(s, getter->type(), Option(ArrayAsPointer)); mandel@1: QString tmp_name = "__tmp_" + getter->name(); mandel@1: s << tmp_name << " = "; mandel@1: mandel@1: if (getter->wasPublic()) mandel@1: qt_return_value += java_field->name(); mandel@1: else mandel@1: qt_return_value += getter->name() + "_getter()"; mandel@1: s << qt_return_value << ";" << endl; mandel@1: mandel@1: writeQtToJava(s, getter->type(), tmp_name, java_return_value, 0, -1, EnumAsInts); eldar@33: if (getter->type()->isTargetLangString() || getter->type()->name() == "QModelIndex") mandel@1: ; mandel@1: else if(getter->type()->typeEntry()->isStructInD()) eldar@81: ; //s << INDENT << "return " << tmp_name << ";" << endl; mandel@1: else mandel@1: s << INDENT << "return " << java_return_value << ";" << endl; mandel@1: } mandel@1: s << "}" << endl << endl; mandel@1: } mandel@1: mandel@1: if(notWrappedYet(setter)) mandel@1: return; mandel@1: mandel@1: // Setter mandel@1: if (mod.isWritable() && !java_field->type()->isConstant()) { mandel@1: // Write public override for protected fields mandel@1: if (setter->wasProtected()) { mandel@1: writeFunctionSignature(s, setter, setter->ownerClass()); mandel@1: s << endl mandel@1: << "{" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: mandel@1: Q_ASSERT(setter->arguments().count() > 0); mandel@1: const AbstractMetaArgument *argument = setter->arguments().at(0); mandel@1: mandel@1: QString thisRef = java_field->isStatic() mandel@1: ? setter->ownerClass()->qualifiedCppName() + QString("::") mandel@1: : QString("this->"); mandel@1: writeAssignment(s, thisRef + java_field->name(), argument->indexedName(), argument->type()); mandel@1: } mandel@1: s << "}" << endl << endl; mandel@1: } mandel@1: mandel@1: writeFunctionName(s, setter, setter->ownerClass()); mandel@1: s << endl; mandel@1: writeFinalFunctionArguments(s, setter); mandel@1: s << "{" << endl; mandel@1: mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: mandel@1: writeFinalFunctionSetup(s, setter, "__qt_object", setter->ownerClass()); mandel@1: mandel@1: Q_ASSERT(setter->arguments().count() == 1); mandel@1: const AbstractMetaArgument *argument = setter->arguments().at(0); mandel@1: mandel@1: QString dest; mandel@1: if (setter->isStatic()) mandel@1: dest = shellClassName(setter->ownerClass()) + "::"; mandel@1: else mandel@1: dest = "__qt_object->"; mandel@1: mandel@1: QString src; eldar@33: if (!argument->type()->isPrimitive() && !argument->type()->typeEntry()->isStructInD()) { mandel@1: src = "__qt_" + argument->indexedName(); eldar@33: } else if (argument->type()->name() == "QModelIndex") { eldar@33: src = "qtd_to_QModelIndex(" + argument->indexedName() + ")"; eldar@33: } else mandel@1: src = argument->indexedName(); mandel@1: mandel@1: if (setter->wasPublic()) mandel@1: writeAssignment(s, dest + java_field->name(), src, argument->type()); mandel@1: else mandel@1: s << INDENT << dest << setter->name() << "_setter(" << src << ");" << endl; mandel@1: } mandel@1: s << "}" << endl << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeFinalDestructor(QTextStream &s, const AbstractMetaClass *cls) mandel@1: { maxter@354: if (cls->hasConstructors() && cls->isDestructorBase()) { maxter@357: s << INDENT << "QTD_EXTERN QTD_DLL_PUBLIC void qtd_" << cls->name() << "_delete(void* nativeId)" << endl eldar@294: << INDENT << "{" << endl maxter@354: << INDENT << " delete (" << shellClassName(cls) << "*)nativeId;" << endl eldar@294: << INDENT << "}" << endl << endl; eldar@294: maxter@357: s << INDENT << "QTD_EXTERN QTD_DLL_PUBLIC void qtd_" << cls->name() << "_destroy(void* nativeId)" << endl eldar@294: << INDENT << "{" << endl maxter@354: << INDENT << " call_destructor((" << shellClassName(cls) << "*)nativeId);" << endl eldar@294: << INDENT << "}" << endl << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeFinalConstructor(QTextStream &s, mandel@1: const AbstractMetaFunction *java_function, mandel@1: const QString &qt_object_name, eldar@293: const QString &java_object_name, eldar@293: const QString &place) mandel@1: { mandel@1: const AbstractMetaClass *cls = java_function->ownerClass(); mandel@1: AbstractMetaArgumentList arguments = java_function->arguments(); mandel@1: QString className = cls->typeEntry()->qualifiedCppName(); mandel@1: mandel@1: bool hasShellClass = cls->generateShellClass(); mandel@1: mandel@1: s << INDENT << shellClassName(cls) << " *" << qt_object_name eldar@293: << " = new " << place << shellClassName(cls) mandel@1: << "("; mandel@1: writeFunctionCallArguments(s, java_function, "__qt_"); mandel@1: s << ");" << endl; mandel@1: s << INDENT << "return (void *) " << qt_object_name << ";" << endl; // qtd mandel@1: mandel@1: /* qtd s << INDENT << "QtJambiLink *__qt_java_link = "; mandel@1: if (cls->isQObject()) { mandel@1: s << "qtjambi_construct_qobject(__jni_env, " << java_object_name << ", " mandel@1: << qt_object_name << ")"; mandel@1: } else { mandel@1: s << "qtjambi_construct_object(__jni_env, " << java_object_name << ", " << qt_object_name; mandel@1: if (cls->typeEntry()->isValue()) mandel@1: s << ", \"" << className << "\")"; mandel@1: else // non-QObject, object type mandel@1: s << ", QMetaType::Void, QLatin1String(\"" << cls->fullName().replace(".", "/") << "\"), true)"; mandel@1: } mandel@1: s << ";" << endl mandel@1: << INDENT << "if (!__qt_java_link) {" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << INDENT << "qWarning(\"object construction failed for type: " mandel@1: << className << "\");" << endl mandel@1: << INDENT << "return;" << endl; mandel@1: } mandel@1: s << INDENT << "}" << endl; mandel@1: mandel@1: mandel@1: if (cls->isQObject()) { mandel@1: // Make sure all qobjects created by Java are owned by java only if mandel@1: // parent object has not been set. mandel@1: // All other objects will default to split ownership. mandel@1: s << INDENT << "if(!__qt_this->QObject::parent()){" << endl; mandel@1: s << INDENT << " __qt_java_link->setJavaOwnership(__jni_env, " << java_object_name << ");" << endl; mandel@1: s << INDENT << "}" << endl; mandel@1: } else { mandel@1: // All non-qobjects created by Java are owned by java mandel@1: s << INDENT << "__qt_java_link->setJavaOwnership(__jni_env, " << java_object_name << ");" << endl; mandel@1: } mandel@1: mandel@1: if (hasCustomDestructor(cls)) { mandel@1: s << INDENT << "__qt_java_link->setDestructorFunction(qtjambi_destructor);" << endl; mandel@1: } mandel@1: mandel@1: if (cls->typeEntry()->typeFlags() & ComplexTypeEntry::DeleteInMainThread) mandel@1: s << INDENT << "__qt_java_link->setDeleteInMainThread(true);" << endl; mandel@1: mandel@1: if (!cls->hasVirtualFunctions() && !cls->hasInconsistentFunctions() && !cls->typeEntry()->isObject()) mandel@1: return; mandel@1: mandel@1: if (hasShellClass) { mandel@1: // Set up the link object mandel@1: s << INDENT << qt_object_name << "->m_link = __qt_java_link;" << endl; mandel@1: mandel@1: // Make sure the user data in the QObject has bindings to the qobject's meta object mandel@1: // (this has to be done after the link is set, so that the fake meta object mandel@1: // can access the java object, for which it gets a reference in the link) mandel@1: if (cls->isQObject()) mandel@1: s << INDENT << qt_object_name << "->m_link->setMetaObject(" << qt_object_name << "->metaObject());" << endl; mandel@1: mandel@1: s << INDENT << qt_object_name << "->m_link->setCreatedByJava(true);" << endl; mandel@1: mandel@1: mandel@1: mandel@1: AbstractMetaClassList interfaces = cls->interfaces(); mandel@1: if (interfaces.size() + (cls->baseClass() != 0 ? 1 : 0) > 1) { mandel@1: if (cls->baseClass() != 0) mandel@1: interfaces += cls->baseClass(); mandel@1: foreach (AbstractMetaClass *iface, interfaces) { mandel@1: AbstractMetaClass *impl = iface->isInterface() ? iface->primaryInterfaceImplementor() : iface; mandel@1: s << INDENT << qt_object_name << "->m_link->registerSubObject((" << impl->qualifiedCppName() << " *) " << qt_object_name << ");" << endl; mandel@1: } mandel@1: } mandel@1: } mandel@1: mandel@1: if (!cls->hasVirtualFunctions() && !cls->hasInconsistentFunctions()) mandel@1: return; mandel@1: mandel@1: // Set up the vtable mandel@1: s << INDENT; mandel@1: QString space(24, ' '); mandel@1: if (hasShellClass) mandel@1: s << qt_object_name << "->m_vtable = "; mandel@1: s << "qtjambi_setup_vtable(__jni_env, " << endl << space << "__jni_object, " << endl; mandel@1: mandel@1: if (cls->hasInconsistentFunctions()) { mandel@1: s << space << "qtjambi_inconsistent_count, " << endl mandel@1: << space << "qtjambi_inconsistent_names, " << endl mandel@1: << space << "qtjambi_inconsistent_signatures, " << endl; mandel@1: } else { mandel@1: s << space << "0, 0, 0, // no inconsistent functions" << endl; mandel@1: } mandel@1: mandel@1: if (cls->hasVirtualFunctions()) { mandel@1: s << space << "qtjambi_method_count, " << endl mandel@1: << space << "qtjambi_method_names, " << endl mandel@1: << space << "qtjambi_method_signatures" << endl; mandel@1: } else { mandel@1: s << space << "0, 0, 0 // no virtual functions" << endl; mandel@1: } mandel@1: mandel@1: s << space << ");" << endl; */ mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeSignalInitialization(QTextStream &s, const AbstractMetaClass *java_class) mandel@1: { mandel@1: if (!java_class->isQObject() mandel@1: || java_class->queryFunctions(AbstractMetaClass::Signals | AbstractMetaClass::Visible | AbstractMetaClass::NotRemovedFromTargetLang).size() == 0) { mandel@1: return ; mandel@1: } mandel@1: mandel@1: s << jni_function_signature(java_class->package(), java_class->name(), "__qt_signalInitialization", "jboolean") mandel@1: << endl << "(JNIEnv *__jni_env, jobject java_object, jlong ptr, jstring java_signal_name)" << endl mandel@1: << "{" << endl mandel@1: << " QtJambiLink *link = (QtJambiLink *) ptr;" << endl mandel@1: << " if (link == 0)" << endl mandel@1: << " return true;" << endl << endl mandel@1: << " QObject *qt_this = link->qobject();" << endl mandel@1: << " Q_ASSERT(qt_this);" << endl << endl mandel@1: << " QtJambi_SignalWrapper_" << java_class->name() << " *qt_wrapper = " mandel@1: << " (QtJambi_SignalWrapper_" << java_class->name() << " *) link->signalWrapper();" << endl mandel@1: << " if (qt_wrapper == 0) {" << endl mandel@1: << " qt_wrapper = new QtJambi_SignalWrapper_" << java_class->name() << ";" << endl mandel@1: << " link->setSignalWrapper(qt_wrapper);" << endl mandel@1: << " qt_wrapper->link = link;" << endl << endl mandel@1: << " qtjambi_resolve_signals(__jni_env," << endl mandel@1: << " java_object," << endl mandel@1: << " qt_wrapper->m_signals," << endl mandel@1: << " qtjambi_signal_count," << endl mandel@1: << " (char **) qtjambi_signal_names," << endl mandel@1: << " (int *) qtjambi_signal_argumentcounts);" << endl mandel@1: << " }" << endl mandel@1: << " QString signal_name = qtjambi_to_qstring(__jni_env, java_signal_name);" << endl mandel@1: << " return qtjambi_connect_cpp_to_java(__jni_env," << endl mandel@1: << " signal_name," << endl mandel@1: << " qt_this," << endl mandel@1: << " qt_wrapper," << endl mandel@1: << " QLatin1String(\"" << java_class->fullName() << "\")," << endl mandel@1: << " QLatin1String(\"" << signalWrapperPrefix() << "\"));" << endl mandel@1: << "}"; mandel@1: } mandel@1: mandel@1: QString CppImplGenerator::fromObject(const TypeEntry *entry, mandel@1: const QString &var_name) mandel@1: { mandel@1: QString returned; mandel@1: QString package = entry->javaPackage(); mandel@1: const ComplexTypeEntry *centry = entry->isComplex() mandel@1: ? static_cast(entry) mandel@1: : 0; mandel@1: mandel@1: if (centry == 0 || centry->polymorphicIdValue().isEmpty()) { mandel@1: /* qtd returned = "qtjambi_from_object(__jni_env, " + var_name + ", \"" mandel@1: + entry->lookupName() mandel@1: + "\", \"" + QString(package).replace(".", "/") + "/\", true);"; mandel@1: */ mandel@1: if(entry->isObject()) mandel@1: returned = var_name + ";"; mandel@1: else mandel@1: returned = "new " + entry->lookupName() + "(" + var_name +");"; mandel@1: } else { mandel@1: AbstractMetaClass *cls = classes().findClass(centry->qualifiedCppName()); mandel@1: if (!cls) { mandel@1: qFatal("CppImplGenerator::fromObject(): class '%s' could not be resolved...", mandel@1: qPrintable(centry->qualifiedCppName())); mandel@1: } mandel@1: mandel@1: while (cls != 0 && !cls->typeEntry()->isPolymorphicBase()) mandel@1: cls = cls->baseClass(); mandel@1: mandel@1: QString full_name; mandel@1: if (cls != 0) { mandel@1: full_name = cls->fullName(); mandel@1: } else { mandel@1: ReportHandler::warning(QString("class '%1' has polymorphic id but does not inherit a polymorphic class") mandel@1: .arg(centry->qualifiedCppName())); mandel@1: } mandel@1: /* qtd mandel@1: returned = "qtjambi_from_object(__jni_env, " + var_name + ", \"" mandel@1: + centry->lookupName() mandel@1: + "\", \"" + QString(package).replace(".", "/") + "/\"," mandel@1: + "\"" + jni_signature(full_name, Underscores) + "\", true); // fucking complex"; mandel@1: */ mandel@1: if(entry->isObject()) mandel@1: returned = var_name + "; // complex entry"; mandel@1: else mandel@1: returned = "new " + centry->lookupName() + "(" + var_name +"); // complex entry"; mandel@1: } mandel@1: mandel@1: return returned; mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeOriginalMetaObjectFunction(QTextStream &s, const AbstractMetaClass *java_class) mandel@1: { mandel@1: Q_ASSERT(java_class->isQObject()); mandel@1: mandel@1: s << jni_function_signature(java_class->package(), mandel@1: java_class->name(), mandel@1: "originalMetaObject", mandel@1: "jlong"); mandel@1: mandel@1: s << endl mandel@1: << "(JNIEnv *," << endl mandel@1: << " jclass)" << endl mandel@1: << "{" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << INDENT << "return reinterpret_cast(&" << java_class->qualifiedCppName() << "::staticMetaObject);" << endl; mandel@1: } mandel@1: s << "}" << endl << endl; mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeFromNativeFunction(QTextStream &s, const AbstractMetaClass *java_class) mandel@1: { mandel@1: s << jni_function_signature(java_class->package(), mandel@1: java_class->name(), mandel@1: "fromNativePointer", mandel@1: "jobject"); mandel@1: s << endl mandel@1: << "(JNIEnv *__jni_env," << endl mandel@1: << " jclass," << endl mandel@1: << " jobject nativePointer)" << endl mandel@1: << "{" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << INDENT << "void *ptr = qtjambi_to_cpointer(__jni_env, nativePointer, 1);" << endl mandel@1: << INDENT << "return " << fromObject(java_class->typeEntry(), "ptr") << endl mandel@1: << "}" << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeFromArrayFunction(QTextStream &s, const AbstractMetaClass *java_class) mandel@1: { mandel@1: s << jni_function_signature(java_class->package(), mandel@1: java_class->name(), mandel@1: "nativePointerArray", mandel@1: "jobject"); mandel@1: s << endl mandel@1: << "(JNIEnv *__jni_env," << endl mandel@1: << " jclass," << endl mandel@1: << " jobjectArray array)" << endl mandel@1: << "{" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << INDENT << "return qtjambi_array_to_nativepointer(__jni_env, " << endl mandel@1: << INDENT << " array, " << endl mandel@1: << INDENT << " sizeof(" mandel@1: << java_class->qualifiedCppName() << "));" << endl; mandel@1: } mandel@1: s << "}" << endl; mandel@1: } mandel@1: mandel@1: mandel@1: void CppImplGenerator::writeInterfaceCastFunction(QTextStream &s, mandel@1: const AbstractMetaClass *java_class, mandel@1: const AbstractMetaClass *interface) mandel@1: { mandel@1: Q_ASSERT(interface->isInterface()); mandel@1: const InterfaceTypeEntry *ie = static_cast(interface->typeEntry()); mandel@1: QString interface_name = ie->origin()->targetLangName(); mandel@1: mandel@1: s << endl mandel@1: << jni_function_signature(java_class->package(), mandel@1: java_class->name(), mandel@1: QString("__qt_cast_to_%1").arg(interface_name), mandel@1: "jlong", mandel@1: "__J"); mandel@1: mandel@1: s << endl mandel@1: << "(JNIEnv *," << endl mandel@1: << " jobject," << endl mandel@1: << " jlong ptr)" << endl mandel@1: << "{" << endl mandel@1: << " return (jlong) (" << interface->primaryInterfaceImplementor()->qualifiedCppName() << " *) " mandel@1: << "(" << java_class->qualifiedCppName() << " *) ptr;" << endl mandel@1: << "}" << endl; mandel@1: } mandel@1: mandel@1: bool CppImplGenerator::writeConversionRule(QTextStream &s, mandel@1: TypeSystem::Language target_language, mandel@1: const AbstractMetaFunction *java_function, mandel@1: int argument_index, mandel@1: const QString &qt_name, mandel@1: const QString &java_name) mandel@1: { mandel@1: if (argument_index < 0 || java_function == 0) mandel@1: return false; mandel@1: mandel@1: QString conversion_rule = java_function->conversionRule(target_language, argument_index); mandel@1: mandel@1: if (!conversion_rule.isEmpty()) { mandel@1: QString qt_name_var; mandel@1: QString java_name_var; mandel@1: mandel@1: if ((argument_index == 0 && target_language == TypeSystem::NativeCode) mandel@1: || (argument_index != 0 && target_language == TypeSystem::ShellCode)) { mandel@1: qt_name_var = "%in"; mandel@1: java_name_var = "%out"; mandel@1: } else { mandel@1: qt_name_var = "%out"; mandel@1: java_name_var = "%in"; mandel@1: } mandel@1: mandel@1: conversion_rule = conversion_rule.replace(qt_name_var, qt_name) mandel@1: .replace(java_name_var, java_name); mandel@1: mandel@1: AbstractMetaArgumentList arguments = java_function->arguments(); mandel@1: for (int i=0; iindexedName()); mandel@1: } mandel@1: mandel@1: QStringList lines = conversion_rule.split("\n"); mandel@1: foreach (QString line, lines) { mandel@1: s << INDENT << line.trimmed() << endl; mandel@1: } mandel@1: mandel@1: return true; mandel@1: } else { mandel@1: return false; mandel@1: } mandel@1: } mandel@1: mandel@1: mandel@1: void CppImplGenerator::writeJavaToQt(QTextStream &s, mandel@1: const AbstractMetaClass *java_class, mandel@1: const AbstractMetaType *function_return_type, mandel@1: const QString &qt_name, mandel@1: const QString &java_name, mandel@1: const AbstractMetaFunction *java_function, mandel@1: int argument_index) mandel@1: { mandel@1: // Conversion to C++: Shell code for return values, native code for arguments mandel@1: TypeSystem::Language lang = argument_index == 0 ? TypeSystem::ShellCode : TypeSystem::NativeCode; mandel@1: if (writeConversionRule(s, lang, java_function, argument_index, qt_name, java_name)) mandel@1: return; mandel@1: mandel@1: s << INDENT << shellClassName(java_class) << " *" << qt_name << " = (" mandel@1: << shellClassName(java_class) << " *) "; mandel@1: if (java_class->isQObject()) mandel@1: s << "qtjambi_to_qobject"; mandel@1: else mandel@1: s << "qtjambi_to_object"; mandel@1: s << "(__jni_env, " << java_name << ");" << endl; mandel@1: if (java_class->isQObject()) { mandel@1: // ### throw exceptions when objects are null... mandel@1: s << INDENT << "if (!" << qt_name << ") " mandel@1: << default_return_statement_java(function_return_type) << ";" << endl << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: mandel@1: void CppImplGenerator::writeJavaToQt(QTextStream &s, mandel@1: const AbstractMetaType *java_type, mandel@1: const QString &qt_name, mandel@1: const QString &java_name, mandel@1: const AbstractMetaFunction *java_function, mandel@1: int argument_index, mandel@1: Option options) mandel@1: { mandel@1: // Conversion to C++: Shell code for return values, native code for arguments mandel@1: TypeSystem::Language lang = argument_index == 0 ? TypeSystem::ShellCode : TypeSystem::NativeCode; mandel@1: if (java_function && writeConversionRule(s, lang, java_function, argument_index, qt_name, java_name)) mandel@1: return; mandel@1: mandel@1: if (java_type == 0) { mandel@1: QString warn = QString("no conversion possible for argument '%1' in function '%2::%3' for " mandel@1: "language '%4'") mandel@1: .arg(argument_index) mandel@1: .arg(java_function->implementingClass()->name()) mandel@1: .arg(java_function->name()) mandel@1: .arg(int(lang)); mandel@1: ReportHandler::warning(warn); mandel@1: return; mandel@1: } mandel@1: if (java_type->name() == "QModelIndex") { mandel@1: s << INDENT << "QModelIndex " << qt_name << " = qtd_to_QModelIndex(" mandel@1: << java_name << ");" << endl; mandel@1: } else if (java_type->typeEntry()->isStructInD()) { mandel@1: // empty mandel@1: } else if (java_type->typeEntry() && java_type->typeEntry()->qualifiedCppName() == "QString") { mandel@1: s << INDENT << "QString " << qt_name eldar@33: << " = " << QString("QString::fromUtf8((const char *)%1.ptr, %1.length);").arg(java_name) << endl; mandel@1: } else if (java_type->isJObjectWrapper()) { mandel@1: s << INDENT << "JObjectWrapper " << qt_name mandel@1: << " = qtjambi_to_jobjectwrapper(__jni_env, " << java_name << ");" << endl; mandel@1: } else if (java_type->isVariant()) { mandel@1: s << INDENT << "QVariant " << qt_name mandel@1: << " = " << java_name << " == NULL ? QVariant() : QVariant(*" << java_name << ");" << endl; mandel@1: } else if (java_type->isArray() && java_type->arrayElementType()->isPrimitive()) { mandel@1: AbstractMetaType *elementType = java_type->arrayElementType(); mandel@1: mandel@1: // ### Don't assert on wrong array lengths eldar@33: // s << INDENT << "Q_ASSERT(__jni_env->GetArrayLength((jarray) " << java_name << ") == " << java_type->arrayElementCount() << ");" << endl; mandel@1: s << INDENT; mandel@1: writeTypeInfo(s, elementType); eldar@33: s << " *" << qt_name << " = ("; eldar@33: writeTypeInfo(s, elementType); eldar@33: s << "*) " << java_name << ";" << endl; eldar@33: /* mandel@1: s << INDENT << "__jni_env->" << getXxxArrayRegion(elementType) << "( (" << translateType(java_type, options) mandel@1: << ")" << java_name << ", 0, " << java_type->arrayElementCount() << ", " mandel@1: << "(" << translateType(elementType, options) << " *" << ")" mandel@1: << qt_name << ");" << endl; eldar@33: */ mandel@1: } else if (java_type->isArray()) { mandel@1: AbstractMetaType *elementType = java_type->arrayElementType(); mandel@1: mandel@1: s << INDENT << "Q_ASSERT(__jni_env->GetArrayLength((jarray) " << java_name << ") == " << java_type->arrayElementCount() << ");" << endl; mandel@1: writeTypeInfo(s, elementType); mandel@1: s << "[" << java_type->arrayElementCount() << "]" << qt_name << ";" << endl; mandel@1: mandel@1: for (int i=0; iarrayElementCount(); ++i) { mandel@1: writeJavaToQt(s, elementType, qt_name + "[" + QString::number(i) + "]", mandel@1: "__jni_env->GetObjectArrayElement(" + java_name + ", " + QString::number(i) + ")", 0, -1, options); mandel@1: } mandel@1: mandel@1: } else if (java_type->isTargetLangString()) { mandel@1: s << INDENT << "QString " << qt_name mandel@1: << " = " << "QString::fromUtf8(" << java_name << ", " << java_name << "_size);" << endl; mandel@1: // qtd << " = qtjambi_to_qstring(__jni_env, (jstring) " << java_name << ");" << endl; mandel@1: mandel@1: } else if (java_type->isTargetLangChar()) { mandel@1: s << INDENT << "QChar " << qt_name mandel@1: << " = (ushort)" << java_name << ";" << endl; mandel@1: mandel@1: } else if (java_type->isEnum() || java_type->isFlags()) { mandel@1: mandel@1: bool written = false; mandel@1: if (java_type->isEnum()) { mandel@1: AbstractMetaEnum *java_enum = mandel@1: m_classes.findEnum(static_cast(java_type->typeEntry())); mandel@1: if (java_enum && !java_enum->isPublic()) { mandel@1: mandel@1: s << INDENT << "int " << qt_name << " = "; mandel@1: written = true; mandel@1: } mandel@1: } mandel@1: mandel@1: if (!written) { mandel@1: QString qualified_name = java_type->typeEntry()->qualifiedCppName(); mandel@1: s << INDENT << qualified_name << " " << qt_name mandel@1: << " = (" << qualified_name << ") "; mandel@1: } mandel@1: mandel@1: if ((options & EnumAsInts) == 0 && (java_type->isTargetLangEnum() || java_type->isTargetLangFlags())) { eldar@33: s << java_name << ";" << endl; mandel@1: mandel@1: } else if (options & BoxedPrimitive) { mandel@1: const PrimitiveTypeEntry *pentry = TypeDatabase::instance()->findTargetLangPrimitiveType("int"); mandel@1: Q_ASSERT(pentry); mandel@1: mandel@1: s << java_name << ";" << endl; mandel@1: mandel@1: } else { mandel@1: s << java_name << ';' << endl; mandel@1: } mandel@1: mandel@1: } else if (java_type->isContainer()) { mandel@1: writeJavaToQtContainer(s, java_type, qt_name, java_name, 0, -1); mandel@1: mandel@1: } else if (java_type->isThread()) { mandel@1: s << INDENT << "QThread *" << qt_name << " = qtjambi_to_thread(__jni_env, " << java_name mandel@1: << ");" << endl; mandel@1: mandel@1: } else if (java_type->typeEntry()->isCustom()) { mandel@1: const CustomTypeEntry *custom_type = mandel@1: static_cast(java_type->typeEntry()); mandel@1: s << INDENT; mandel@1: custom_type->generateCppJavaToQt(s, java_type, "__jni_env", qt_name, java_name); mandel@1: s << ";" << endl; mandel@1: mandel@1: } else { mandel@1: mandel@1: const TypeEntry *type = java_type->typeEntry(); mandel@1: QString class_name = type->name(); mandel@1: QString qualified_class_name = fixCppTypeName(type->qualifiedCppName()); mandel@1: mandel@1: // Declaration and the c-cast mandel@1: s << INDENT; mandel@1: writeTypeInfo(s, java_type); mandel@1: s << ' ' << qt_name << " = ("; mandel@1: writeTypeInfo(s, java_type); mandel@1: s << ") "; mandel@1: mandel@1: if (java_type->isPrimitive()) { mandel@1: if (options & BoxedPrimitive) { mandel@1: const PrimitiveTypeEntry *pentry = static_cast(type); mandel@1: //std::cout << "---error_here " << type->targetLangName().toStdString() << " \n"; mandel@1: //std::cout << "----func_here " << java_function->marshalledName().toStdString() << " \n"; mandel@1: mandel@1: if (!pentry->preferredConversion()) mandel@1: pentry = TypeDatabase::instance()->findTargetLangPrimitiveType(pentry->targetLangName()); mandel@1: Q_ASSERT(pentry); mandel@1: mandel@1: s << java_name << ";" << endl; mandel@1: mandel@1: } else if ((options & GlobalRefJObject) && type->jniName() == QLatin1String("jobject")) { mandel@1: s << "__jni_env->NewGlobalRef(" << java_name << ");" << endl; mandel@1: } else { mandel@1: s << java_name << ';' << endl; mandel@1: } mandel@1: mandel@1: #if 0 mandel@1: } else if (java_type->isEnum()) { mandel@1: s << "qtjambi_to_enum(__jni_env, " << java_name << ");" << endl; mandel@1: #endif mandel@1: mandel@1: } else if ((java_type->isQObject() || java_type->isObject()) mandel@1: && static_cast(type)->designatedInterface()) { mandel@1: /* qtd const InterfaceTypeEntry *ie = mandel@1: static_cast(type)->designatedInterface(); mandel@1: s << "qtjambi_to_interface(__jni_env, "; mandel@1: mandel@1: // This cast is only valid if we're dealing with a native id mandel@1: if ((options & UseNativeIds) == UseNativeIds) mandel@1: s << "(QtJambiLink *)"; mandel@1: */ mandel@1: s << java_name << ";" << endl; mandel@1: /* qtd mandel@1: s << "\"" << ie->targetLangName() << "\", \"" mandel@1: << ie->javaPackage().replace(".", "/") << "/\", " mandel@1: << "\"__qt_cast_to_" << type->targetLangName() << "\");" << endl; mandel@1: */ mandel@1: } else if (java_type->isObject() || java_type->isQObject() || java_type->isNativePointer()) { mandel@1: if (java_type->isReference()) { mandel@1: s << "* (" << qualified_class_name << " " mandel@1: << QString(java_type->actualIndirections(), '*') << ") "; mandel@1: } mandel@1: mandel@1: if (java_type->isNativePointer()) { mandel@1: /* qtd s << "qtjambi_to_cpointer(" mandel@1: << "__jni_env, " mandel@1: << java_name << ", " mandel@1: << java_type->actualIndirections() << ");" << endl; */ mandel@1: s << java_name << ";" << endl; // qtd mandel@1: }/* qtd else if (java_type->isQObject()) { mandel@1: if ((options & UseNativeIds) == 0) mandel@1: s << "qtjambi_to_qobject(__jni_env, "; mandel@1: else mandel@1: s << "qtjambi_from_jlong("; mandel@1: s << java_name; mandel@1: s << ");" << endl; mandel@1: }*/ else { mandel@1: /* qtd if ((options & UseNativeIds) == 0) mandel@1: s << "qtjambi_to_object(__jni_env, "; mandel@1: else mandel@1: s << "qtjambi_from_jlong("; mandel@1: */ s << java_name; mandel@1: s << ";" << endl; // + mandel@1: // qtd s << ");" << endl; mandel@1: } mandel@1: mandel@1: } else { mandel@1: // Return values... mandel@1: if (argument_index == 0) { mandel@1: s << "(" << java_name << " != 0 ? *(" << qualified_class_name << " *)"; mandel@1: /* qtd if ((options & UseNativeIds) == 0) mandel@1: s << "qtjambi_to_object(__jni_env, "; mandel@1: else mandel@1: s << "qtjambi_from_jlong("; mandel@1: */ s << java_name; mandel@1: s << " : " << qualified_class_name << "());" << endl; mandel@1: } else { mandel@1: s << "*" mandel@1: << "(" << qualified_class_name << " *)"; mandel@1: bool null_check = false; mandel@1: /* qtd if ((options & UseNativeIds) == 0) { mandel@1: s << "qtjambi_to_object(__jni_env, "; mandel@1: } else if (hasDefaultConstructor(java_type)) { mandel@1: null_check = true; mandel@1: s << "(" << java_name << " != 0 ? qtjambi_from_jlong("; mandel@1: } else { mandel@1: s << "qtjambi_from_jlong("; mandel@1: } mandel@1: */ s << java_name; mandel@1: // qtd s << ")"; mandel@1: mandel@1: if (null_check) mandel@1: s << " : default_" << QString(qualified_class_name).replace("::", "_") << "())"; mandel@1: s << ";" << endl; mandel@1: } mandel@1: mandel@1: } mandel@1: } mandel@1: // qtd s << INDENT << "QTJAMBI_EXCEPTION_CHECK(__jni_env);" << endl; mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeQtToJava(QTextStream &s, mandel@1: const AbstractMetaType *java_type, mandel@1: const QString &qt_name, mandel@1: const QString &java_name, mandel@1: const AbstractMetaFunction *java_function, mandel@1: int argument_index, mandel@1: Option option) mandel@1: { mandel@1: mandel@1: // Conversion to Java: Native code for return values, shell code for arguments mandel@1: TypeSystem::Language lang = argument_index == 0 ? TypeSystem::NativeCode : TypeSystem::ShellCode; mandel@1: /* qtd if (java_function && writeConversionRule(s, lang, java_function, argument_index, qt_name, java_name)) mandel@1: return; mandel@1: */ mandel@1: if (java_type == 0) { mandel@1: QString warn = QString("no conversion possible for argument '%1' in function '%2::%3' for " mandel@1: "language '%4'") mandel@1: .arg(argument_index) mandel@1: .arg(java_function->implementingClass()->name()) mandel@1: .arg(java_function->name()) mandel@1: .arg(int(lang)); mandel@1: ReportHandler::warning(warn); mandel@1: return; mandel@1: } mandel@1: mandel@1: if (java_type->name() == "QModelIndex") { mandel@1: QString prefix = "*"; mandel@1: if (option & BoxedPrimitive) mandel@1: s << INDENT << "QModelIndexAccessor tmp_index = qtd_from_QModelIndex(" << qt_name << ");" << endl mandel@1: << INDENT << "QModelIndexAccessor *" << java_name << " = &tmp_index;" << endl; mandel@1: else mandel@1: s << INDENT << "*" << java_name << " = qtd_from_QModelIndex(" << qt_name << ");" << endl; mandel@1: eldar@81: } else if (java_type->typeEntry()->isStructInD()) { eldar@81: if (option & BoxedPrimitive) { eldar@81: s << INDENT << java_type->typeEntry()->name() << " *" << java_name << " = (" eldar@81: << java_type->typeEntry()->name() << " *) &" << qt_name << ";" << endl; eldar@81: } else { eldar@81: s << INDENT << "*" << java_name << " = " << qt_name << ";" << endl; eldar@81: } mandel@1: } else if (java_type->isArray() && java_type->arrayElementType()->isPrimitive()) { mandel@1: AbstractMetaType *elementType = java_type->arrayElementType(); eldar@33: /* qtd mandel@1: s << INDENT << translateType(java_type, option) << " " << java_name << " = __jni_env->" << newXxxArray(elementType) mandel@1: << "(" << java_type->arrayElementCount() << ");" << endl; mandel@1: mandel@1: s << INDENT << "__jni_env->" << setXxxArrayRegion(elementType) << "(" mandel@1: << "(" << translateType(java_type, option) << ")" << java_name mandel@1: << ", 0, " << java_type->arrayElementCount() << ", " mandel@1: << "(" << translateType(elementType, option) << " *" << ")" mandel@1: << qt_name << ");" << endl; eldar@33: */ eldar@33: s << INDENT << translateType(java_type, option) << " " << java_name << " = " << qt_name << ";" <isArray()) { mandel@1: AbstractMetaType *elementType = java_type->arrayElementType(); mandel@1: mandel@1: s << INDENT << "jobject " << java_name << " = __jni_env->NewObjectArray(" mandel@1: << java_type->arrayElementCount() << ");" << endl; mandel@1: mandel@1: s << "jobject __qt_element = 0;"; mandel@1: mandel@1: for (int i=0; iarrayElementCount(); ++i) { mandel@1: writeQtToJava(s, elementType, qt_name + "[" + QString::number(i) + "]", mandel@1: "__qt_element", 0, -1, option); mandel@1: s << "__jni_env->SetObjectArrayElement((jobjectArray) " << java_name << ", " mandel@1: << i << ", __qt_element);" << endl; mandel@1: } mandel@1: mandel@1: } else if (java_type->isPrimitive()) { mandel@1: const PrimitiveTypeEntry *type = mandel@1: static_cast(java_type->typeEntry()); mandel@1: mandel@1: Q_ASSERT(type); mandel@1: QString ret_val; mandel@1: if (java_function) mandel@1: ret_val = jniReturnName(java_function); mandel@1: else mandel@1: ret_val = fixCppTypeName(java_type->typeEntry()->qualifiedCppName()); mandel@1: s << INDENT << ret_val << " " << java_name << " = " << qt_name << ";" << endl; mandel@1: } else if (java_type->isJObjectWrapper()) { mandel@1: s << INDENT << "jobject " << java_name << " = qtjambi_from_jobjectwrapper(__jni_env, " mandel@1: << qt_name << ");" << endl; mandel@1: } else if (java_type->isVariant()) { mandel@1: s << INDENT << "QVariant *" << java_name mandel@1: << " = new QVariant(" << qt_name << ");" << endl; mandel@1: } else if (java_type->isTargetLangString()) { eldar@35: if(java_type->typeEntry()->qualifiedCppName() == "QStringRef") { eldar@35: s << INDENT << "const QString *str_ref = " << qt_name << ".string();" << endl eldar@35: << INDENT << "if(str_ref)" << endl maxter@253: << INDENT << " qtd_toUtf8(str_ref->utf16(), str_ref->size(), " << java_name << ");" << endl eldar@35: << INDENT << "else {" << endl eldar@35: << INDENT << " QString empty_str;" << endl maxter@253: << INDENT << " qtd_toUtf8(empty_str.utf16(), empty_str.size(), " << java_name << ");" << endl eldar@35: << INDENT << "}" << endl; eldar@35: } else { maxter@253: s << INDENT << QString("qtd_toUtf8(%1.utf16(), %1.size(), %2);").arg(qt_name, java_name) << endl; eldar@35: } mandel@1: } else if (java_type->isTargetLangChar()) { mandel@1: s << INDENT << "jchar " << java_name << " = " << qt_name << ".unicode();" << endl; mandel@1: mandel@1: } else if (java_type->isIntegerEnum() || java_type->isIntegerFlags() mandel@1: || ((option & EnumAsInts) && (java_type->isEnum() || java_type->isFlags()))) { mandel@1: // } else if (java_type->isEnum() || java_type->isFlags()) { mandel@1: mandel@1: // if (option & EnumAsInts) { mandel@1: // qDebug() << java_type->name() << "should be int..."; mandel@1: // } mandel@1: mandel@1: /* if (option & BoxedPrimitive) { mandel@1: s << INDENT << "jobject " << java_name << " = qtjambi_from_int(__jni_env, " mandel@1: << qt_name << ");" << endl; mandel@1: } else */{ mandel@1: s << INDENT << "int " << java_name << " = " << qt_name << ";" << endl; mandel@1: } mandel@1: mandel@1: } else if (java_type->isTargetLangEnum()) { mandel@1: Q_ASSERT((option & EnumAsInts) == 0); mandel@1: const EnumTypeEntry *et = static_cast(java_type->typeEntry()); mandel@1: s << INDENT << "int " << java_name << " = " << qt_name << ";" << endl; mandel@1: mandel@1: } else if (java_type->isTargetLangFlags()) { mandel@1: Q_ASSERT((option & EnumAsInts) == 0); mandel@1: const FlagsTypeEntry *ft = static_cast(java_type->typeEntry()); mandel@1: s << INDENT << "jobject " << java_name << " = qtjambi_from_flags(__jni_env, " mandel@1: << qt_name << ", \"" << ft->javaPackage().replace('.', '/') << '/' mandel@1: << ft->originator()->javaQualifier() << '$' << ft->targetLangName() << "\");" << endl; mandel@1: mandel@1: } else if (java_type->isContainer()) { mandel@1: writeQtToJavaContainer(s, java_type, qt_name, java_name, 0, -1); mandel@1: mandel@1: } else if (java_type->isThread()) { mandel@1: s << INDENT << "jobject " << java_name << " = qtjambi_from_thread(__jni_env, " << qt_name mandel@1: << ");" << endl; mandel@1: mandel@1: } else if (!java_type->isNativePointer() && java_type->typeEntry()->isCustom()) { mandel@1: s << INDENT; mandel@1: static_cast(java_type->typeEntry()) mandel@1: ->generateCppQtToJava(s, java_type, "__jni_env", qt_name, java_name); mandel@1: s << ";" << endl; mandel@1: mandel@1: } else { mandel@1: QString return_type; mandel@1: if (java_function) mandel@1: return_type = jniReturnName(java_function); mandel@1: else { mandel@1: return_type = jniReturnType(java_type); mandel@1: return_type = fixCppTypeName(return_type); mandel@1: // return_type = fixCppTypeName(java_type->typeEntry()->qualifiedCppName()); mandel@1: } mandel@1: /* if( (java_type->isValue() && !java_type->typeEntry()->isStructInD()) mandel@1: || java_type->isObject() ) mandel@1: s << INDENT << return_type << " *" << java_name << " = (" << return_type << "*) "; mandel@1: else*/ mandel@1: s << INDENT << return_type << " " << java_name << " = (" << return_type << ") "; mandel@1: mandel@1: if (java_type->isQObject()) { mandel@1: /* qtd s << "qtjambi_from_qobject(__jni_env, " << "(QObject *) "; mandel@1: mandel@1: if (java_type->isReference() && java_type->indirections() == 0) mandel@1: s << "&"; mandel@1: mandel@1: s << qt_name mandel@1: << ", \"" << java_type->typeEntry()->lookupName() << "\"" mandel@1: << ", \"" << java_type->package().replace(".", "/") << "/\"" mandel@1: << ");" << endl; mandel@1: */ mandel@1: s << qt_name << ";" << endl; mandel@1: mandel@1: #if 0 mandel@1: } else if (java_type->isEnum()) { mandel@1: mandel@1: const EnumTypeEntry *et = static_cast(java_type->typeEntry()); mandel@1: s << "qtjambi_from_enum(__jni_env, " << qt_name << ", \"" mandel@1: << et->javaQualifier() << "$" << et->targetLangName() << "\");" << endl; mandel@1: #endif mandel@1: } else if (java_type->isNativePointer()) { mandel@1: /* qtd s << "qtjambi_from_cpointer(__jni_env, "; mandel@1: if (java_type->isReference()) mandel@1: s << "&"; mandel@1: s << qt_name << ", " << nativePointerType(java_type) << ", " mandel@1: << java_type->actualIndirections() << ");" << endl; mandel@1: */ mandel@1: if (java_type->isReference()) mandel@1: s << "&"; mandel@1: s << qt_name << ";" << "// qtjambi_from_cpointer" << endl; mandel@1: } else if (java_type->isValue()) { mandel@1: // qtd s << fromObject(java_type->typeEntry(), "&" + qt_name) << endl; mandel@1: s << "new " << java_type->typeEntry()->qualifiedCppName() << "(" << qt_name << ");" << endl; mandel@1: } else { mandel@1: // qtd s << fromObject(java_type->typeEntry(), mandel@1: // qtd (java_type->isReference() ? "&" : "") + qt_name) << endl; Eldar@378: if (java_type->isReference()) Eldar@378: s << "&"; mandel@1: s << qt_name << ";" << endl; mandel@1: } mandel@1: } mandel@1: mandel@1: } mandel@1: mandel@1: QString CppImplGenerator::getTypeName(const TypeEntry *entry, Option option) mandel@1: { mandel@1: if(entry->isEnum() && (option & EnumAsInts)) mandel@1: return "int"; mandel@1: mandel@1: return entry->lookupName(); mandel@1: } mandel@1: mandel@1: void CppImplGenerator::writeQtToJavaContainer(QTextStream &s, mandel@1: const AbstractMetaType *java_type, mandel@1: const QString &qt_name, mandel@1: const QString &java_name, mandel@1: const AbstractMetaFunction *java_function, mandel@1: int argument_index) mandel@1: { mandel@1: // Language for conversion to Java: Native code for return values and Shell code for arguments mandel@1: TypeSystem::Language lang = argument_index == 0 ? TypeSystem::NativeCode : TypeSystem::ShellCode; mandel@1: if (java_function && writeConversionRule(s, lang, java_function, argument_index, qt_name, java_name)) mandel@1: return; mandel@1: mandel@1: if (java_type == 0) { mandel@1: QString warn = QString("no conversion possible for argument '%1' in function '%2::%3' for " mandel@1: "language '%4'") mandel@1: .arg(argument_index) mandel@1: .arg(java_function->implementingClass()->name()) mandel@1: .arg(java_function->name()) mandel@1: .arg(int(lang)); mandel@1: ReportHandler::warning(warn); mandel@1: return; mandel@1: } mandel@1: mandel@1: Q_ASSERT(java_type->isContainer()); mandel@1: const ContainerTypeEntry *type = mandel@1: static_cast(java_type->typeEntry()); mandel@1: eldar@298: if (type->type() == ContainerTypeEntry::VectorContainer mandel@1: || type->type() == ContainerTypeEntry::LinkedListContainer mandel@1: || type->type() == ContainerTypeEntry::StackContainer mandel@1: || type->type() == ContainerTypeEntry::SetContainer mandel@1: || type->type() == ContainerTypeEntry::QueueContainer) { mandel@1: mandel@1: Q_ASSERT(java_type->instantiations().size() == 1); mandel@1: AbstractMetaType *targ = java_type->instantiations().first(); mandel@1: mandel@1: QString cls_name = getTypeName(targ->typeEntry(), EnumAsInts); mandel@1: cls_name.remove("_ConcreteWrapper"); mandel@1: mandel@1: s << endl mandel@1: << INDENT; mandel@1: mandel@1: switch (type->type()) { mandel@1: case ContainerTypeEntry::LinkedListContainer: mandel@1: case ContainerTypeEntry::QueueContainer: mandel@1: s << "qtjambi_linkedlist_new(__jni_env)"; mandel@1: break; mandel@1: case ContainerTypeEntry::StackContainer: mandel@1: s << "qtjambi_stack_new(__jni_env)"; mandel@1: break; mandel@1: case ContainerTypeEntry::SetContainer: mandel@1: s << "qtjambi_hashset_new(__jni_env)"; mandel@1: break; mandel@1: default: mandel@1: s << "qtd_allocate_" << cls_name mandel@1: << "_array(" << java_name << ", " << qt_name << ".size())"; mandel@1: break; mandel@1: } mandel@1: mandel@1: s << ";" << endl mandel@1: << INDENT; mandel@1: mandel@1: mandel@1: writeTypeInfo(s, java_type, ForceValueType); eldar@167: QString index = "i_" + qt_name; mandel@1: s << "::const_iterator " << qt_name << "_end_it = " << qt_name << ".constEnd();" << endl eldar@167: << INDENT << QString("int %0 = 0;").arg(index) << endl mandel@1: << INDENT; mandel@1: s << "for ("; mandel@1: writeTypeInfo(s, java_type, ForceValueType); mandel@1: s << "::const_iterator " << qt_name << "_it = " << qt_name << ".constBegin(); " mandel@1: << qt_name << "_it != " << qt_name << "_end_it; ++" << qt_name << "_it) {" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << INDENT; mandel@1: writeTypeInfo(s, targ); mandel@1: s << " __qt_tmp = *" << qt_name << "_it;" << endl; mandel@1: mandel@1: if(targ->isTargetLangString()) eldar@167: s << INDENT << "void *__java_tmp = qtd_string_from_array(" << java_name << ", " << index << ");" << endl; mandel@1: mandel@1: writeQtToJava(s, targ, "__qt_tmp", "__java_tmp", 0, -1, BoxedPrimitive); mandel@1: eldar@167: s << INDENT << "qtd_assign_" << cls_name << "_array_element(" << java_name << ", " << index << ", __java_tmp);" << endl; eldar@167: s << INDENT << "++" << index << ";" << endl; mandel@1: } eldar@167: s << INDENT << "}" << endl; eldar@298: eldar@298: } else if (type->isQList()) { eldar@298: // QList & list2 = (*(QList *)nativeId); eldar@298: writeTypeInfo(s, java_type, ForceValueType); eldar@298: s << "&" << java_name << "_tmp = (*("; eldar@298: writeTypeInfo(s, java_type, ForceValueType); eldar@298: s << "*)" << java_name << ");" << endl eldar@298: << INDENT << java_name << "_tmp = " << qt_name << ";" << endl; mandel@1: mandel@1: } else if (type->type() == ContainerTypeEntry::PairContainer) { mandel@1: QList args = java_type->instantiations(); mandel@1: Q_ASSERT(args.size() == 2); mandel@1: mandel@1: s << INDENT << "jobject " << java_name << ";" << endl mandel@1: << INDENT << "{" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: writeQtToJava(s, args.at(0), qt_name + ".first", "__java_tmp_first", 0, -1, BoxedPrimitive); mandel@1: writeQtToJava(s, args.at(1), qt_name + ".second", "__java_tmp_second", 0, -1, BoxedPrimitive); mandel@1: s << INDENT << java_name << " = qtjambi_pair_new(__jni_env, " mandel@1: << "__java_tmp_first, __java_tmp_second);" << endl; mandel@1: } mandel@1: mandel@1: s << INDENT << "}" << endl; mandel@1: mandel@1: } else if (type->type() == ContainerTypeEntry::MultiMapContainer) { mandel@1: mandel@1: Q_ASSERT(java_type->instantiations().size() == 2); mandel@1: AbstractMetaType *targ_key = java_type->instantiations().at(0); mandel@1: AbstractMetaType *targ_val = java_type->instantiations().at(1); mandel@1: mandel@1: s << endl mandel@1: << INDENT << "jobject " << java_name << " = qtjambi_treemap_new(__jni_env, " << qt_name << ".keys().size());" << endl mandel@1: << INDENT << "QList<"; mandel@1: writeTypeInfo(s, targ_key); mandel@1: s << "> __qt_keys = " << qt_name << ".keys();" << endl mandel@1: << INDENT << "for (int i=0; i<__qt_keys.size(); ++i) {" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: mandel@1: s << INDENT; mandel@1: writeTypeInfo(s, targ_key); mandel@1: s << " __qt_tmp_key = __qt_keys.at(i);" << endl; mandel@1: writeQtToJava(s, targ_key, "__qt_tmp_key", "__java_tmp_key", 0, -1, BoxedPrimitive); mandel@1: mandel@1: s << INDENT << "QList<"; mandel@1: writeTypeInfo(s, targ_val); mandel@1: s << "> __qt_values = " << qt_name << ".values(__qt_tmp_key);" << endl mandel@1: << INDENT << "jobject __java_value_list = qtjambi_arraylist_new(__jni_env, __qt_values.size());" << endl mandel@1: << INDENT << "for (int j=0; j<__qt_values.size(); ++j) {" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: mandel@1: s << INDENT; mandel@1: writeTypeInfo(s, targ_val); mandel@1: s << " __qt_tmp_val = __qt_values.at(j);" << endl; mandel@1: writeQtToJava(s, targ_val, "__qt_tmp_val", "__java_tmp_val", 0, -1, BoxedPrimitive); mandel@1: mandel@1: s << INDENT << "qtjambi_collection_add(__jni_env, __java_value_list, __java_tmp_val);" << endl; mandel@1: } mandel@1: s << INDENT << "}" << endl mandel@1: << INDENT << "qtjambi_map_put(__jni_env, " << java_name << ", __java_tmp_key, __java_value_list);" << endl; mandel@1: } mandel@1: s << INDENT << "}" << endl; mandel@1: mandel@1: } else if (type->type() == ContainerTypeEntry::MapContainer mandel@1: || type->type() == ContainerTypeEntry::HashContainer) { mandel@1: QString constructor = type->type() == ContainerTypeEntry::MapContainer mandel@1: ? "qtjambi_treemap_new" mandel@1: : "qtjambi_hashmap_new"; mandel@1: mandel@1: Q_ASSERT(java_type->instantiations().size() == 2); mandel@1: AbstractMetaType *targ_key = java_type->instantiations().at(0); mandel@1: AbstractMetaType *targ_val = java_type->instantiations().at(1); mandel@1: mandel@1: s << endl mandel@1: << INDENT << "jobject " << java_name << " = " << constructor << "(__jni_env, " << qt_name mandel@1: << ".size());" << endl mandel@1: << INDENT; mandel@1: writeTypeInfo(s, java_type, Option(ExcludeReference | ExcludeConst)); mandel@1: s << "::const_iterator it;" << endl mandel@1: << INDENT << "for (it=" << qt_name << ".constBegin(); it!=" << qt_name << ".constEnd(); ++it) {" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << INDENT; mandel@1: writeTypeInfo(s, targ_key); mandel@1: s << " __qt_tmp_key = it.key();" << endl mandel@1: << INDENT; mandel@1: writeTypeInfo(s, targ_val); mandel@1: s << " __qt_tmp_val = it.value();" << endl; mandel@1: writeQtToJava(s, targ_key, "__qt_tmp_key", "__java_tmp_key", 0, -1, BoxedPrimitive); mandel@1: writeQtToJava(s, targ_val, "__qt_tmp_val", "__java_tmp_val", 0, -1, BoxedPrimitive); mandel@1: s << INDENT << "qtjambi_map_put(__jni_env, " << java_name mandel@1: << ", __java_tmp_key, __java_tmp_val);" << endl; mandel@1: } mandel@1: s << INDENT << "}" << endl; mandel@1: mandel@1: } else { mandel@1: ReportHandler::warning(QString("unable to generate container type %1, type=%2") mandel@1: .arg(java_type->name()).arg(type->type())); mandel@1: } mandel@1: mandel@1: // qtd s << INDENT << "QTJAMBI_EXCEPTION_CHECK(__jni_env);" << endl; mandel@1: } mandel@1: mandel@1: mandel@1: void CppImplGenerator::writeJavaToQtContainer(QTextStream &s, mandel@1: const AbstractMetaType *java_type, mandel@1: const QString &qt_name, mandel@1: const QString &java_name, mandel@1: const AbstractMetaFunction *java_function, mandel@1: int argument_index) mandel@1: { mandel@1: // Conversion to C++: Shell code for return value, native code for arguments mandel@1: TypeSystem::Language lang = argument_index == 0 ? TypeSystem::ShellCode : TypeSystem::NativeCode; mandel@1: if (java_function && writeConversionRule(s, lang, java_function, argument_index, qt_name, java_name)) mandel@1: return; mandel@1: mandel@1: if (java_type == 0) { mandel@1: QString warn = QString("no conversion possible for argument '%1' in function '%2::%3' for " mandel@1: "language '%4'") mandel@1: .arg(argument_index) mandel@1: .arg(java_function->implementingClass()->name()) mandel@1: .arg(java_function->name()) mandel@1: .arg(int(lang)); mandel@1: ReportHandler::warning(warn); mandel@1: return; mandel@1: } mandel@1: mandel@1: mandel@1: Q_ASSERT(java_type->isContainer()); mandel@1: const ContainerTypeEntry *type = mandel@1: static_cast(java_type->typeEntry()); mandel@1: eldar@298: if (type->type() == ContainerTypeEntry::VectorContainer mandel@1: || type->type() == ContainerTypeEntry::LinkedListContainer mandel@1: || type->type() == ContainerTypeEntry::StackContainer mandel@1: || type->type() == ContainerTypeEntry::SetContainer mandel@1: || type->type() == ContainerTypeEntry::QueueContainer) { mandel@1: Q_ASSERT(java_type->instantiations().size() == 1); mandel@1: AbstractMetaType *targ = java_type->instantiations().first(); mandel@1: QString elem_type = getTypeName(targ->typeEntry(), EnumAsInts); mandel@1: elem_type.remove("_ConcreteWrapper"); mandel@1: mandel@1: s << INDENT; mandel@1: writeTypeInfo(s, java_type, ForceValueType); mandel@1: s << qt_name << ";" << endl; mandel@1: mandel@1: { mandel@1: if (type->type() == ContainerTypeEntry::VectorContainer mandel@1: || type->type() == ContainerTypeEntry::StackContainer) eldar@298: s << INDENT << qt_name << ".reserve(" << java_name << "->length);" << endl; eldar@298: eldar@298: s << INDENT << "for (int i=0; i<" << java_name << "->length; ++i) {" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: if(targ->isTargetLangString()) eldar@35: s << INDENT << "DArray __d_element;" << endl eldar@298: << INDENT << "qtd_get_string_from_array(" << java_name << "->ptr, i, &__d_element);" << endl; mandel@1: else { mandel@1: s << INDENT; eldar@33: writeTypeInfo(s, targ, Option(VirtualDispatch | ForcePointer | EnumAsInts)); mandel@1: QString cast_string = ""; mandel@1: const TypeEntry* centry = targ->typeEntry(); mandel@1: if (centry->isComplex() && (centry->isObject() || centry->isValue() || centry->isInterface())) mandel@1: cast_string = "(void**)"; mandel@1: s << "__d_element;" << endl mandel@1: << INDENT << "qtd_get_" << elem_type << "_from_array(" << java_name << ", i, &__d_element);" << endl; mandel@1: } mandel@1: writeJavaToQt(s, targ, "__qt_element", "__d_element", 0, -1, BoxedPrimitive); mandel@1: QString cont_element = "__qt_element"; mandel@1: if(targ->typeEntry()->isStructInD() && targ->name() != "QModelIndex") mandel@1: cont_element = "__d_element"; mandel@1: s << INDENT << qt_name << " << " << cont_element << ";" << endl; mandel@1: } mandel@1: // qtd s << INDENT << "}" << endl; mandel@1: } mandel@1: s << INDENT << "}" << endl; eldar@298: } else if (type->isQList()) { eldar@298: writeTypeInfo(s, java_type, ForceValueType); eldar@298: s << qt_name << " = (*("; eldar@298: writeTypeInfo(s, java_type, ForceValueType); eldar@298: s << "*)" << java_name << ");" << endl; mandel@1: } else if (type->type() == ContainerTypeEntry::PairContainer) { mandel@1: QList targs = java_type->instantiations(); mandel@1: Q_ASSERT(targs.size() == 2); mandel@1: mandel@1: s << INDENT; mandel@1: writeTypeInfo(s, java_type, ForceValueType); mandel@1: s << " " << qt_name << ";" << endl mandel@1: << INDENT << "if (" << java_name << " != 0) {" << endl; mandel@1: { mandel@1: // separate scope required just in case function takes two QPair's. mandel@1: Indentation indent(INDENT); mandel@1: s << INDENT << "jobject __java_first = qtjambi_pair_get(__jni_env, " mandel@1: << java_name << ", 0);" << endl; mandel@1: writeJavaToQt(s, targs.at(0), "__qt_first", "__java_first", 0, -1, BoxedPrimitive); mandel@1: mandel@1: s << INDENT << "jobject __java_second = qtjambi_pair_get(__jni_env, " mandel@1: << java_name << ", 1);" << endl; mandel@1: writeJavaToQt(s, targs.at(1), "__qt_second", "__java_second", 0, -1, BoxedPrimitive); mandel@1: mandel@1: s << INDENT << qt_name << ".first = __qt_first;" << endl mandel@1: << INDENT << qt_name << ".second = __qt_second;" << endl; mandel@1: } mandel@1: s << INDENT << "}" << endl; mandel@1: } else if (type->type() == ContainerTypeEntry::MapContainer mandel@1: || type->type() == ContainerTypeEntry::HashContainer) { mandel@1: Q_ASSERT(java_type->instantiations().size() == 2); mandel@1: AbstractMetaType *targ_key = java_type->instantiations().at(0); mandel@1: AbstractMetaType *targ_val = java_type->instantiations().at(1); mandel@1: mandel@1: s << INDENT; mandel@1: writeTypeInfo(s, java_type, ForceValueType); mandel@1: s << qt_name << ";" << endl; mandel@1: s << INDENT << "if (" << java_name << " != 0) {" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << INDENT << "int __qt_list_size = qtjambi_map_size(__jni_env, " << java_name mandel@1: << ");" << endl mandel@1: << INDENT mandel@1: << "jobjectArray __java_entry_set = qtjambi_map_entryset_array(__jni_env, " << java_name mandel@1: << ");" << endl; mandel@1: mandel@1: s << INDENT << "for (int i=0; i<__qt_list_size; ++i) {" << endl; mandel@1: { mandel@1: Indentation indent(INDENT); mandel@1: s << INDENT mandel@1: << "QPair __java_entry = " mandel@1: << "qtjambi_entryset_array_get(__jni_env, __java_entry_set, i);" mandel@1: << endl mandel@1: << INDENT << "jobject __java_key = __java_entry.first;" << endl mandel@1: << INDENT << "jobject __java_val = __java_entry.second;" << endl; mandel@1: writeJavaToQt(s, targ_key, "__qt_key", "__java_key", 0, -1, BoxedPrimitive); mandel@1: writeJavaToQt(s, targ_val, "__qt_val", "__java_val", 0, -1, BoxedPrimitive); mandel@1: s << INDENT << qt_name << ".insert(__qt_key, __qt_val);" << endl; mandel@1: } mandel@1: s << INDENT << "}" << endl; mandel@1: } mandel@1: s << INDENT << "}" << endl; mandel@1: mandel@1: } else { mandel@1: ReportHandler::warning(QString("unable to generate container type %1, %2") mandel@1: .arg(java_type->name()).arg(type->type())); mandel@1: } mandel@1: mandel@1: } mandel@1: mandel@1: mandel@1: void CppImplGenerator::writeFunctionCall(QTextStream &s, const QString &object_name, mandel@1: const AbstractMetaFunction *java_function, mandel@1: const QString &prefix, mandel@1: Option option, mandel@1: const QStringList &extra_arguments) mandel@1: { mandel@1: QString function_name = option & OriginalName ? java_function->originalName() : java_function->name(); mandel@1: mandel@1: AbstractMetaClassList interfaces = java_function->implementingClass()->interfaces(); mandel@1: mandel@1: QString classPrefix; mandel@1: if (prefix.isEmpty() mandel@1: && !java_function->implementingClass()->interfaces().isEmpty() mandel@1: && !java_function->implementingClass()->inheritsFrom(java_function->declaringClass())) { mandel@1: classPrefix = java_function->declaringClass()->qualifiedCppName() + "::"; mandel@1: } mandel@1: mandel@1: if (java_function->isInGlobalScope()) { mandel@1: mandel@1: // Global scope stream operators need the arguments to be reordered (this ref at end) mandel@1: // so we special case them in order to simplify this code mandel@1: bool stream_operator = java_function->originalName() == "operator<<" mandel@1: || java_function->originalName() == "operator>>"; mandel@1: mandel@1: if (java_function->type() == 0) mandel@1: s << "if (" << object_name << " != 0) "; mandel@1: else mandel@1: s << "(" << object_name << " != 0) ? "; mandel@1: s << "::" << prefix << function_name << "("; mandel@1: if (!stream_operator) mandel@1: s << "*" << object_name << ", "; mandel@1: writeFunctionCallArguments(s, java_function, "__qt_"); mandel@1: if (stream_operator) mandel@1: s << ", *" << object_name; mandel@1: s << ")"; mandel@1: if (java_function->type() != 0) mandel@1: s << " : " << default_return_statement_qt(java_function->type(), Generator::Option(option | Generator::NoReturnStatement)); mandel@1: s << ";"; mandel@1: } else { mandel@1: s << object_name << (java_function->isStatic() ? QLatin1String("::") : QLatin1String("->") + classPrefix) mandel@1: << prefix << function_name << "("; mandel@1: writeFunctionCallArguments(s, java_function, "__qt_"); mandel@1: mandel@1: // The extra arguments... mandel@1: for (int i=0; i 0 || java_function->arguments().size() != 0) mandel@1: s << ", "; mandel@1: s << extra_arguments.at(i); mandel@1: } mandel@1: mandel@1: s << ");"; mandel@1: } mandel@1: mandel@1: s << endl; mandel@1: mandel@1: } mandel@1: mandel@1: mandel@1: void CppImplGenerator::writeFunctionCallArguments(QTextStream &s, mandel@1: const AbstractMetaFunction *java_function, mandel@1: const QString &prefix, mandel@1: Option options) mandel@1: { mandel@1: AbstractMetaArgumentList arguments = java_function->arguments(); mandel@1: mandel@1: int written_arguments = 0; mandel@1: const AbstractMetaClass *cls = java_function->ownerClass(); maxter@355: if (java_function->isConstructor() && cls->isPolymorphic()) { mandel@1: s << "d_ptr"; mandel@1: written_arguments++; mandel@1: } mandel@1: for (int i=0; itype(); mandel@1: mandel@1: if ((options & SkipRemovedArguments) == SkipRemovedArguments mandel@1: && java_function->argumentRemoved(i+1)) { mandel@1: continue; mandel@1: } mandel@1: mandel@1: if (written_arguments++ > 0) { mandel@1: s << ", "; mandel@1: } mandel@1: mandel@1: bool enum_as_int = (options & EnumAsInts) && (argument->type()->typeEntry()->isEnum() mandel@1: || argument->type()->typeEntry()->isFlags()); mandel@1: if (a_type->isEnum()) { mandel@1: AbstractMetaEnum *java_enum = mandel@1: m_classes.findEnum(static_cast(argument->type()->typeEntry())); mandel@1: if (java_enum == 0) { mandel@1: ReportHandler::warning(QString("enum not found: '%1'") mandel@1: .arg(argument->type()->typeEntry()->qualifiedCppName())); mandel@1: } else { mandel@1: enum_as_int |= !java_enum->isPublic(); mandel@1: } mandel@1: } mandel@1: mandel@1: if ( (options & VirtualDispatch) mandel@1: && a_type->isContainer()) { eldar@298: if ( ((const ContainerTypeEntry *)a_type->typeEntry())->isQList() ) eldar@298: s << "(void*)&" << argument->indexedName(); eldar@298: else eldar@298: s << "__d_" << argument->indexedName(); mandel@1: continue; mandel@1: } mandel@1: mandel@1: if ((!(options & NoCasts) && !enum_as_int) || ((options & ForceEnumCast) && a_type->isEnum())) { mandel@1: mandel@1: // If the type in the signature is specified without template instantiation, but the mandel@1: // class is actually a template class, then we have troubles. mandel@1: AbstractMetaClass *cls = classes().findClass(argument->type()->typeEntry()->qualifiedCppName()); mandel@1: mandel@1: if ( (options & VirtualDispatch) && !a_type->typeEntry()->isStructInD() mandel@1: && ( a_type->isValue() mandel@1: || (a_type->isReference() && (a_type->typeEntry()->isValue() || a_type->typeEntry()->isObject() || a_type->typeEntry()->isPrimitive()) && !a_type->isTargetLangString()) mandel@1: ) ) mandel@1: s << "&"; mandel@1: mandel@1: if( (options & VirtualDispatch) && a_type->typeEntry()->isStructInD() && a_type->isReference()) mandel@1: s << "&"; mandel@1: mandel@1: if ( (options & VirtualDispatch) mandel@1: && ( a_type->isTargetLangString() || a_type->name() == "QModelIndex" ) ) mandel@1: ; mandel@1: else if (cls == 0 || cls->templateArguments().size() == a_type->instantiations().size()) { mandel@1: s << "("; mandel@1: writeTypeInfo(s, a_type, options); mandel@1: s << ")"; mandel@1: } mandel@1: } mandel@1: mandel@1: if (a_type->isNativePointer() && a_type->typeEntry()->name() == "QString" && !a_type->isReference()) mandel@1: s << "&"; mandel@1: mandel@1: if ( ( !a_type->isPrimitive() mandel@1: || !java_function->conversionRule(TypeSystem::NativeCode, argument->argumentIndex()+1).isEmpty() ) mandel@1: && (!a_type->typeEntry()->isStructInD() || a_type->name() == "QModelIndex") ) { mandel@1: s << prefix; mandel@1: } mandel@1: mandel@1: if (options & VirtualDispatch) { mandel@1: if( argument->type()->isTargetLangString()) mandel@1: s << argument->indexedName() << ".utf16(), " << argument->indexedName() << ".size()"; mandel@1: else if (argument->type()->name() == "QModelIndex") mandel@1: s << "qtd_from_QModelIndex(" << argument->indexedName() << ")"; mandel@1: else mandel@1: s << argument->indexedName(); mandel@1: } else mandel@1: s << argument->indexedName(); mandel@1: } mandel@1: } mandel@1: mandel@1: mandel@1: QString CppImplGenerator::translateType(const AbstractMetaType *java_type, Option option, bool d_export) mandel@1: { mandel@1: if (!java_type) mandel@1: return "void"; mandel@1: mandel@1: const TypeEntry *type = java_type->typeEntry(); mandel@1: QString class_name = type->name(); mandel@1: QString qualified_class_name = fixCppTypeName(type->qualifiedCppName()); mandel@1: QString d_name = qualified_class_name; mandel@1: if (d_export) mandel@1: d_name = type->lookupName(); mandel@1: mandel@1: if (java_type->isPrimitive() mandel@1: || java_type->isTargetLangString() mandel@1: || java_type->isVariant() mandel@1: || java_type->isJObjectWrapper() eldar@33: || java_type->isTargetLangChar()) { mandel@1: return d_name; eldar@33: } else if (java_type->isArray()) { eldar@39: if (d_export) eldar@39: return java_type->arrayElementType()->name() + "*"; eldar@39: else eldar@39: return java_type->arrayElementType()->typeEntry()->qualifiedCppName() + "*"; mandel@1: } else if (java_type->isIntegerEnum() || java_type->isIntegerFlags() eldar@33: || ((option & EnumAsInts) && (java_type->isEnum() || java_type->isFlags()))) { eldar@33: return "int"; eldar@33: } else if (java_type->isReference()) { eldar@33: if (java_type->typeEntry()->isValue()) eldar@33: return "void*"; eldar@33: else eldar@33: return d_name + " "+ QString(java_type->actualIndirections(), '*'); eldar@33: } else if (java_type->isNativePointer()) { eldar@190: if (java_type->typeEntry()->isStructInD() && dVersion == 2 && java_type->isConstant() && d_export) eldar@190: return "const(" + d_name + QString(java_type->indirections()-1, '*') + ")*"; eldar@190: else if (java_type->typeEntry()->isValue()) eldar@33: return "void*"; eldar@33: else if (java_type->typeEntry()->isEnum() && d_export) eldar@33: return "int" + QString(java_type->indirections(), '*'); eldar@188: else { eldar@188: if (java_type->isConstant() && dVersion == 2 && d_export) eldar@190: return "const (" + d_name + QString(java_type->indirections(), '*') + ")"; eldar@188: else eldar@188: return d_name + QString(java_type->indirections(), '*'); eldar@188: } eldar@33: } else { eldar@33: return d_name + QString(java_type->indirections(), '*'); eldar@33: } eldar@81: } mandel@1: mandel@1: void CppImplGenerator::writeExtraIncludes(QTextStream &s, const AbstractMetaClass *java_class) mandel@1: { mandel@1: IncludeList includes = java_class->typeEntry()->extraIncludes(); mandel@1: qSort(includes.begin(), includes.end()); mandel@1: mandel@1: int used = 0; mandel@1: foreach (const Include &i, includes) { mandel@1: if (i.type != Include::TargetLangImport) { mandel@1: s << i.toString() << endl; mandel@1: ++used; mandel@1: } mandel@1: } mandel@1: mandel@1: mandel@1: if (used) mandel@1: s << endl; mandel@1: mandel@1: } mandel@1: mandel@1: mandel@1: void CppImplGenerator::writeDefaultConstructedValues_helper(QSet &values, mandel@1: const AbstractMetaFunction *func) mandel@1: { mandel@1: foreach (AbstractMetaArgument *arg, func->arguments()) { mandel@1: AbstractMetaType *type = arg->type(); mandel@1: if (func->typeReplaced(arg->argumentIndex()+1).isEmpty() && type->isValue() && hasDefaultConstructor(type)) mandel@1: values << type->typeEntry()->qualifiedCppName(); mandel@1: } mandel@1: } mandel@1: mandel@1: mandel@1: void CppImplGenerator::writeDefaultConstructedValues(QTextStream &s, const AbstractMetaClass *java_class) { mandel@1: mandel@1: QSet values; mandel@1: mandel@1: // Class functions, more or less copied from the logic in write(Class) above... mandel@1: AbstractMetaFunctionList class_funcs; mandel@1: mandel@1: // Add normal final functions mandel@1: foreach (AbstractMetaFunction *function, java_class->functionsInTargetLang()) { mandel@1: if (!function->isEmptyFunction()) mandel@1: class_funcs << function; mandel@1: } mandel@1: mandel@1: // Add abstract functions, I think... mandel@1: foreach (AbstractMetaFunction *function, java_class->queryFunctions(AbstractMetaClass::NormalFunctions mandel@1: | AbstractMetaClass::AbstractFunctions mandel@1: | AbstractMetaClass::NotRemovedFromTargetLang)) { mandel@1: if (function->implementingClass() != java_class) mandel@1: class_funcs << function; mandel@1: } mandel@1: mandel@1: // Signals (their c++ wrapper calls actually...) mandel@1: class_funcs += java_class->queryFunctions(AbstractMetaClass::Signals); mandel@1: mandel@1: // mandel@1: foreach (AbstractMetaFunction *f, class_funcs) { mandel@1: writeDefaultConstructedValues_helper(values, f); mandel@1: } mandel@1: mandel@1: foreach (AbstractMetaField *field, java_class->fields()) { mandel@1: writeDefaultConstructedValues_helper(values, field->setter()); mandel@1: } mandel@1: mandel@1: if (!values.isEmpty()) { mandel@1: s << endl << endl mandel@1: << "// Default constructed values used throughout final functions..." << endl; mandel@1: for (QSet::const_iterator it = values.constBegin(); it != values.constEnd(); ++it) { mandel@1: s << "Q_GLOBAL_STATIC(" << *it << ", default_" << QString(*it).replace("::", "_") mandel@1: << ");" << endl; mandel@1: } mandel@1: s << endl << endl; mandel@1: } mandel@1: } e@324: