changeset 355:08c1ca7975ab

obviated redundant virtual dispatch callbacks
author Max Samukha <maxter@spambox.com>
date Tue, 25 May 2010 17:23:11 +0300
parents 18bd68f586c6
children 12cec2d14e1c
files cmake/FindD.cmake cpp/qt_core/QVariant_shell.h cpp/qt_qtd/qtd_core.cpp generator/containergenerator.cpp generator/cppgenerator.cpp generator/cppgenerator.h generator/cppheadergenerator.cpp generator/cppimplgenerator.cpp generator/cppimplgenerator.h generator/dgenerator.cpp generator/dgenerator.h generator/typesystem.cpp generator/typesystem_core.xml include/QObjectEntity.h include/qtd_core.h
diffstat 15 files changed, 251 insertions(+), 185 deletions(-) [+]
line wrap: on
line diff
--- a/cmake/FindD.cmake	Mon May 24 23:43:30 2010 +0300
+++ b/cmake/FindD.cmake	Tue May 25 17:23:11 2010 +0300
@@ -370,7 +370,7 @@
 	set(output_name_tmp ${output_name_tmp}/${name}${CMAKE_EXECUTABLE_SUFFIX})
     elseif("${TYPE_tmp}" STREQUAL "SHARED")
 	if(D_IS_MARS)
-	    message(FATAL_ERROR "DMD not support building shared library")
+	    message(FATAL_ERROR "DMD does not support building shared libraries")
 	endif(D_IS_MARS)
 	if(NOT OUTPUT_PATH_tmp)
 	    if(LIBRARY_OUTPUT_DIRECTORY)
--- a/cpp/qt_core/QVariant_shell.h	Mon May 24 23:43:30 2010 +0300
+++ b/cpp/qt_core/QVariant_shell.h	Tue May 25 17:23:11 2010 +0300
@@ -2,7 +2,7 @@
 #define QVARIANT_SHELL_H
 
 #include <QtCore/QHash>
-#include <QObjectEntity.h>
+#include <qtd_core.h>
 #include <qvariant.h>
 
 #include <QVariant>
--- a/cpp/qt_qtd/qtd_core.cpp	Mon May 24 23:43:30 2010 +0300
+++ b/cpp/qt_qtd/qtd_core.cpp	Tue May 25 17:23:11 2010 +0300
@@ -12,6 +12,8 @@
 #include "qtd_core.h"
 #include <iostream>
 
+uint userDataId;
+
 extern "C" DLL_PUBLIC QModelIndex qtd_to_QModelIndex(QModelIndexAccessor mia)
 {
     return * (QModelIndex *) (&mia) ;
@@ -47,6 +49,8 @@
 extern "C" DLL_PUBLIC void qtd_core_initCallBacks(pfunc_abstr d_func, pfunc_abstr del_d_qobj) {
     QTD_EXPORT_VAR_SET(qtd_toUtf8, d_func);
     QTD_EXPORT_VAR_SET(qtd_QtdObject_delete, del_d_qobj);
+
+    userDataId = QObject::registerUserData();
 }
 #endif
 
@@ -67,3 +71,48 @@
 {
     return qUnregisterResourceData(version, tree, name, data);
 }
+
+//
+// QObjectLink implementation
+//
+
+QObjectLink::QObjectLink(QObject *qObject, void* dId) :
+    QtdObjectLink(dId),
+    flags(None)
+{
+    qObject->setUserData(userDataId, this);
+}
+
+QObjectLink* QObjectLink::getLink(const QObject *qObject)
+{
+    return static_cast<QObjectLink*>(qObject->userData(userDataId));
+}
+
+void* QObjectLink::getDId(const QObject* qObject)
+{
+    QObjectLink* link = getLink(qObject);
+    return link ? link->dId : NULL;
+}
+
+void QObjectLink::destroyLink(QObject* qObject)
+{
+    Q_ASSERT(dId);
+    qtd_QtdObject_delete(dId);
+    if (qObject)
+    {
+        qObject->setUserData(userDataId, NULL);
+        dId = NULL;
+    }
+}
+
+bool QObjectLink::createdByD()
+{
+    return CreatedByD & flags;
+}
+
+QObjectLink::~QObjectLink()
+{
+    if (dId)
+        destroyLink();
+}
+
--- a/generator/containergenerator.cpp	Mon May 24 23:43:30 2010 +0300
+++ b/generator/containergenerator.cpp	Tue May 25 17:23:11 2010 +0300
@@ -475,7 +475,7 @@
       << "package " << d_type << " qtd_" << cls_name << "_cpp_to_d(" << cpp_type << " ret)" << endl
       << "{" << endl;
 
-    marshallFromCppToD(s, centry);
+    marshalFromCppToD(s, centry);
 
     s << "}" << endl;
 }
--- a/generator/cppgenerator.cpp	Mon May 24 23:43:30 2010 +0300
+++ b/generator/cppgenerator.cpp	Tue May 25 17:23:11 2010 +0300
@@ -230,7 +230,7 @@
     s << "(";
     const AbstractMetaClass *owner = java_function->ownerClass();
 
-    bool has_d_ptr = java_function->isConstructor() && owner && (owner->hasVirtualFunctions()/* || owner->typeEntry()->isObject()*/ );
+    bool has_d_ptr = java_function->isConstructor() && owner && (owner->isPolymorphic()/* || owner->typeEntry()->isObject()*/ );
     const AbstractMetaArgumentList arg_list = java_function->arguments();
     if (has_d_ptr) {
         s << "void *d_ptr";
@@ -250,3 +250,20 @@
     if (java_function->isConstant())
         s << " const";
 }
+
+void CppGenerator::writeInclude(QTextStream &s, Include inc)
+{
+    if (!inc.name.isEmpty()) {
+        s << "#include ";
+        if (inc.type == Include::IncludePath)
+            s << "<";
+        else
+            s << "\"";
+        s << inc.name;
+        if (inc.type == Include::IncludePath)
+            s << ">";
+        else
+            s << "\"";
+        s << endl;
+    }
+}
--- a/generator/cppgenerator.h	Mon May 24 23:43:30 2010 +0300
+++ b/generator/cppgenerator.h	Tue May 25 17:23:11 2010 +0300
@@ -72,6 +72,7 @@
     static void writeFunctionArguments(QTextStream &s, const AbstractMetaArgumentList &arguments,
                                 Option option = NoOption,
                                 int numArguments = -1);
+    static void writeInclude(QTextStream &s, Include inc);
 
     QString signalWrapperPrefix() const { return "__qt_signalwrapper_"; }
 
@@ -82,11 +83,10 @@
             && !(java_class->attributes() & AbstractMetaAttributes::Fake);
     }
 
-    static QString shellClassName(const AbstractMetaClass *java_class, bool fullName = true) {
-        if (java_class->generateShellClass())
-            return java_class->name() + "_QtDShell";
-        else
-            return fullName ? java_class->qualifiedCppName() : java_class->typeEntry()->name();
+    static QString shellClassName(const AbstractMetaClass *java_class) {
+        return java_class->generateShellClass()
+               ? java_class->name() + "_QtDShell"
+               : java_class->qualifiedCppName();
     }
 
  protected:
--- a/generator/cppheadergenerator.cpp	Mon May 24 23:43:30 2010 +0300
+++ b/generator/cppheadergenerator.cpp	Tue May 25 17:23:11 2010 +0300
@@ -126,7 +126,7 @@
       << "#define " << include_block << endl << endl
 //      << "#include <qtjambi_core.h>" << endl
       << "#include <QtCore/QHash>" << endl
-      << "#include <QObjectEntity.h>" << endl;
+      << "#include <qtd_core.h>" << endl;
 
     Include inc = java_class->typeEntry()->include();
     s << "#include ";
@@ -178,10 +178,11 @@
 
     s << "class " << shellClassName(java_class)
       << " : public " << java_class->qualifiedCppName();
-    if (java_class->isQObject())
-        s << ", public QtD_QObjectEntity";
-    else if(java_class->hasVirtualFunctions())
-        s << ", public QtD_Entity";
+    if (java_class->isQObject()) {
+        s << ", public QObjectLink";
+    }
+    else if (java_class->isPolymorphic())
+        s << ", public QtdObjectLink";
     s << endl  << "{" << endl;
 
     if (java_class->isQObject()) {
--- a/generator/cppimplgenerator.cpp	Mon May 24 23:43:30 2010 +0300
+++ b/generator/cppimplgenerator.cpp	Tue May 25 17:23:11 2010 +0300
@@ -500,15 +500,15 @@
     AbstractMetaFunctionList virtualFunctions = java_class->virtualFunctions();
     for (int pos = 0; pos<virtualFunctions.size(); ++pos) {
         const AbstractMetaFunction *function = virtualFunctions.at(pos);
-        if (!notWrappedYet(function)) { // qtd2
-            s << "    " << function->marshalledName() << "_dispatch = "
-                 "(pf" << function->marshalledName() << "_dispatch) virts[" << pos << "];" << endl;
+        if (!notWrappedYet(function) && java_class == function->declaringClass()) { // qtd2
+            s << "    " << function->marshalledName(false) << "_dispatch = "
+                 "(pf" << function->marshalledName(false) << "_dispatch) virts[" << pos << "];" << endl;
         }
     }
     // D-side signal callbacks
-    if (java_class->isQObject()) {
-        s << "    qtd_" << java_class->name() << "_qt_metacall_dispatch = (QtMetacallCallback)sigs[0];" << endl
-          << "    qtd_" << java_class->name() << "_metaObject_dispatch = (MetaObjectCallback)sigs[1];" << endl;
+    if (java_class->name() == "QObject") {
+        s << "    qtd_QObject_qt_metacall_dispatch = (QtMetacallCallback)sigs[0];" << endl
+          << "    qtd_QObject_metaObject_dispatch = (MetaObjectCallback)sigs[1];" << endl;
     }
     s << "}" << endl;
 }
@@ -544,27 +544,11 @@
     if (java_class->isQObject())
         s << "#include <qtdynamicmetaobject.h>" << endl;
 */
-    if (java_class->isQObject())
-        s << "#include <QObjectEntity.h>" << endl;
 
     s << "#include <iostream>" << endl;
 
-
-
-    Include inc = java_class->typeEntry()->include();
-    if (!inc.name.isEmpty()) {
-        s << "#include ";
-        if (inc.type == Include::IncludePath)
-            s << "<";
-        else
-            s << "\"";
-        s << inc.name;
-        if (inc.type == Include::IncludePath)
-            s << ">";
-        else
-            s << "\"";
-        s << endl;
-    }
+    writeInclude(s, java_class->typeEntry()->include());
+
     s << endl; // qtd
     s << "#include \"qtd_core.h\"" << endl
       << "#include \"ArrayOpsPrimitive.h\"" << endl
@@ -599,6 +583,7 @@
             if (function->isConstructor() && !function->isPrivate())
                 writeShellConstructor(s, function);
         }
+
         writeShellDestructor(s, java_class);
 
         if (!java_class->isQObject() && java_class->hasVirtualFunctions())
@@ -755,11 +740,11 @@
     s << QString("extern \"C\" DLL_PUBLIC bool qtd_%1_QTypeInfo_isDummy() { return (bool) QTypeInfo<%2>::isDummy; }\n").arg(java_class->name()).arg(java_class->qualifiedCppName());
 }
 
-void CppImplGenerator::writeVirtualDispatchFunction(QTextStream &s, const AbstractMetaFunction *function, bool d_export)
+void CppImplGenerator::writeVirtualDispatchFunction(QTextStream &s, const AbstractMetaFunction *function, const AbstractMetaClass *java_class, bool d_export)
 {
             uint options2 = ReturnType | ExternC;
             QString return_type = jniReturnName(function, options2);
-            QString f_name = function->marshalledName() + "_dispatch";
+            QString f_name = function->marshalledName(false) + "_dispatch";
 
             if(!d_export)
                 s << "extern \"C\" ";
@@ -770,10 +755,14 @@
                 if(!d_export)
                     s << ";";
             } else if (cpp_shared) {
-                s << "typedef " << return_type << " " << "(*pf" << f_name << ")";
-                writeVirtualDispatchArguments(s, function, false);
-                s << ";" << endl
-                  << "pf" << f_name << " " << f_name << ";";
+                if (function->declaringClass() == java_class) {
+                    s << "typedef " << return_type << " " << "(*pf" << f_name << ")";
+                    writeVirtualDispatchArguments(s, function, false);
+                    s << ";" << endl
+                      << "pf" << f_name << " " << f_name << ";";
+                } else {
+                    s << "extern pf" << f_name << " " << f_name << ";";
+                }
             }
 
             s << endl;
@@ -792,7 +781,7 @@
                                       || !new_return_type.isEmpty())
                                       && new_return_type != "void");
 
-            writeVirtualDispatchFunction(s, function);
+            writeVirtualDispatchFunction(s, function, implementor);
 
             writeFunctionSignature(s, function, implementor, QString(), OriginalName);
 
@@ -872,8 +861,11 @@
                         s << "(" << f_type->typeEntry()->qualifiedCppName() <<") ";
                 }
 
-                s << function->marshalledName() << "_dispatch("
-                  << "this->dId";
+                s << function->marshalledName(false) << "_dispatch(";
+                if (implementor->isQObject())
+                    s << "QObjectLink::getLink(this)->dId";
+                else
+                    s << "this->dId";
 
                 if (f_type) {
                     if (f_type->isTargetLangString())
@@ -934,7 +926,7 @@
     uint nativeArgCount = 0;
     AbstractMetaType *ret_type = d_function->type();
 
-    s << "(void *d_entity";
+    s << "(void *dId";
 
     if (ret_type) {
         if (ret_type->isTargetLangString()) {
@@ -1273,13 +1265,13 @@
     QString entityName = java_class->name() + "Entity";
     QString className = java_class->name();
 
-    s << "class " << entityName << " : public QObject, public QtD_QObjectEntity" << endl
+    s << "class " << entityName << " : public QObject, public QObjectLink" << endl
       << "{" << endl
       << "public:" << endl
       << "    Q_OBJECT_CHECK" << endl
       << "//    virtual int qt_metacall(QMetaObject::Call, int, void **);" << endl << endl
 
-      << "    " << entityName << "(QObject *qObject, void *dId) : QObject(), QtD_QObjectEntity(qObject, dId) {}" << endl
+      << "    " << entityName << "(QObject *qObject, void *dId) : QObject(), QObjectLink(qObject, dId) {}" << endl
       << "};" << endl << endl;
 
 /*    // QObject_Link::qt_metacall()
@@ -1352,21 +1344,35 @@
       << "}" << endl << endl;
       */
 
-    if(cpp_shared)
-        s << "MetaObjectCallback qtd_" << java_class->name() << "_metaObject_dispatch;" << endl
-          << "QtMetacallCallback qtd_" << java_class->name() << "_qt_metacall_dispatch;" << endl;
-    else
-        s << "extern \"C\" const QMetaObject* qtd_" << java_class->name() << "_metaObject_dispatch(void *d_entity);" << endl
-          << "extern \"C\" int qtd_" << java_class->name() << "_qt_metacall_dispatch(void *d_entity, QMetaObject::Call _c, int _id, void **_a);" << endl;
-
+    if(cpp_shared) {
+        QString attr;
+        if (java_class->name() == "QObject")
+            attr = "extern ";
+
+        s << attr << "MetaObjectCallback qtd_QObject_metaObject_dispatch;" << endl
+          << attr << "QtMetacallCallback qtd_QObject_qt_metacall_dispatch;" << endl;
+    } else {
+        s << "extern \"C\" const QMetaObject* qtd_QObject_metaObject_dispatch(void *dId);" << endl
+          << "extern \"C\" int qtd_QObject_qt_metacall_dispatch(void *dId, QMetaObject::Call _c, int _id, void **_a);" << endl;
+    }
+
+    // TODO: QMetaObject should be included in the typesystem
     s << endl
       << "const QMetaObject * " << shellClassName(java_class) << "::metaObject() const" << endl
       << "{" << endl
-      << "    return qtd_" << java_class->name() << "_metaObject_dispatch(this->dId);" << endl
+      << "    void* dId = QObjectLink::getDId(this);" << endl
+      << "    if (dId)" << endl
+      << "        return qtd_QObject_metaObject_dispatch(dId);" << endl
+      << "    else" << endl
+      << "        return " << java_class->qualifiedCppName() << "::metaObject();" << endl
       << "}" << endl << endl
       << "int " << shellClassName(java_class) << "::qt_metacall(QMetaObject::Call _c, int _id, void **_a)" << endl
       << "{" << endl
-      << "    return qtd_" << java_class->name() << "_qt_metacall_dispatch(this->dId, _c, _id, _a);" << endl
+      << "    void* dId = QObjectLink::getDId(this);" << endl
+      << "    if (dId)" << endl
+      << "        return qtd_QObject_qt_metacall_dispatch(dId, _c, _id, _a);" << endl
+      << "    else" << endl
+      << "        return " << java_class->qualifiedCppName() << "::qt_metacall(_c, _id, _a);" << endl
       << "}" << endl << endl
 
       << "int " << shellClassName(java_class) << "::__override_qt_metacall(QMetaObject::Call _c, int _id, void **_a)" << endl
@@ -1442,7 +1448,7 @@
         // D-side signal callbacks
         for(int i = 0; i < signal_funcs.size(); i++) {
             AbstractMetaFunction *signal = signal_funcs.at(i);
-            s << "extern \"C\" DLL_PUBLIC void " << signalExternName(java_class, signal) << "_handle(void* d_entity, void** args);" << endl;
+            s << "extern \"C\" DLL_PUBLIC void " << signalExternName(java_class, signal) << "_handle(void* dId, void** args);" << endl;
         }
 
 	if(signal_funcs.size() > 0)
@@ -1479,10 +1485,11 @@
             s << ", ";
     }
     s << ")";
-    if (cls->isQObject())
-        s << "," << endl << "      QtD_QObjectEntity(this, d_ptr)";
-    else if (cls->hasVirtualFunctions())
-        s << "," << endl << "      QtD_Entity(d_ptr)";
+    if (cls->isQObject()) {
+        s << "," << endl << "      QObjectLink(this, d_ptr)";
+    }
+    else if (cls->isPolymorphic())
+        s << "," << endl << "      QtdObjectLink(d_ptr)";
 /* qtd        s << "    m_meta_object(0)," << endl;
     s << "      m_vtable(0)," << endl
       << "      m_link(0)" << endl;
@@ -1503,10 +1510,13 @@
     QString className = shellClassName(java_class);
     s << className << "::~" << className << "() {" << endl;
 
-    if (java_class->isQObject())
-        s << "    destroyEntity(this);";
-    //else if (java_class->isPolymorphic())
-    //    s << "    qtd_QtdObject_delete(dId);" << endl;
+    if (java_class->isQObject()) {
+        s << "    destroyLink(this);" << endl;
+    }
+    /*
+    else if (java_class->isPolymorphic())
+        s << "    qtd_delete_d_object(dId);" << endl;
+    */
 
     s << "}" << endl << endl;
 }
@@ -1828,7 +1838,7 @@
     s << "{" << endl;
     {
         Indentation indent(INDENT);
-            s << INDENT << "QtD_Entity* a = dynamic_cast<QtD_Entity*>((" << java_class->qualifiedCppName() << "*)q_ptr);" << endl
+            s << INDENT << "QtdObjectLink* a = dynamic_cast<QtdObjectLink*>((" << java_class->qualifiedCppName() << "*)q_ptr);" << endl
               << INDENT << "if (a != NULL)" << endl
               << INDENT << "    return a->dId;" << endl
               << INDENT << "else" << endl
@@ -1957,7 +1967,7 @@
     uint nativeArgCount = 0;
     const AbstractMetaClass *cls = java_function->ownerClass();
     if (java_function->isConstructor() &&
-        ( cls->hasVirtualFunctions()
+        ( cls->isPolymorphic()
         || cls->typeEntry()->isObject() ) )
     {
         s << "void *d_ptr";
@@ -1965,7 +1975,7 @@
     }
 
     // passing pointer to C++ object
-    bool hasNativeId = (callThrough && !java_function->isStatic() && !java_function->isConstructor());
+    bool hasNativeId = callThrough && !java_function->isStatic() && !java_function->isConstructor();
     if (hasNativeId) {
         if (nativeArgCount > 0)
             s << "," << endl << " ";
@@ -2176,11 +2186,8 @@
                 function_prefix = "__override_";
                 extra_param.append("__do_static_call");
                 s << INDENT
-                  << "bool __do_static_call = __this_nativeId ? ";
-                if (java_class->isQObject())
-                    s << "dynamic_cast<QtD_QObjectEntity*>((QObject*)__this_nativeId) : false;" << endl;
-                else
-                    s << "__" << java_class->name() << "_entity(__this_nativeId) : false;" << endl;
+                  << "bool __do_static_call = "
+                  << "dynamic_cast<QtdObjectLink*>((" << java_class->polymorphicBase()->qualifiedCppName() << "*)__this_nativeId) != NULL;" << endl;
             } else {
                 option = OriginalName;
             }
@@ -3607,7 +3614,7 @@
 
     int written_arguments = 0;
     const AbstractMetaClass *cls = java_function->ownerClass();
-    if (java_function->isConstructor() && cls->hasVirtualFunctions()) {
+    if (java_function->isConstructor() && cls->isPolymorphic()) {
         s << "d_ptr";
         written_arguments++;
     }
--- a/generator/cppimplgenerator.h	Mon May 24 23:43:30 2010 +0300
+++ b/generator/cppimplgenerator.h	Tue May 25 17:23:11 2010 +0300
@@ -208,7 +208,7 @@
 
     static QString jniReturnName(const AbstractMetaFunction *java_function, uint options = StandardJNISignature, bool d_export = false);
     static void writeVirtualFunctionDispatchName(QTextStream &s, const AbstractMetaFunction *function, bool d_export = false);
-    static void writeVirtualDispatchFunction(QTextStream &s, const AbstractMetaFunction *function, bool d_export = false);
+    static void writeVirtualDispatchFunction(QTextStream &s, const AbstractMetaFunction *function, const AbstractMetaClass *java_class, bool d_export = false);
     static void writeInterfaceCasts(QTextStream &s, const AbstractMetaClass *java_class);
     void writeSignalsHandling(QTextStream &s, const AbstractMetaClass *java_class);
     void writeQObjectLink(QTextStream &s, const AbstractMetaClass *java_class);
--- a/generator/dgenerator.cpp	Mon May 24 23:43:30 2010 +0300
+++ b/generator/dgenerator.cpp	Tue May 25 17:23:11 2010 +0300
@@ -778,25 +778,27 @@
         s << d_function->marshalledName() << "(";
     }
 
+    bool arg_written = false;
+
     if (!d_function->isConstructor() && !d_function->isStatic()) {
-        if(dVersion == 2 && d_function->isConstant())
-            s << "(cast(" << d_function->ownerClass()->name() << ")this).__nativeId";
-        else
-            s << "__nativeId";
+        s << "(cast(" << d_function->ownerClass()->name() << ")this).__nativeId";
+        arg_written = true;
     }
 
     if (d_function->isConstructor() &&
-        ( d_function->implementingClass()->hasVirtualFunctions()
+        ( d_function->ownerClass()->isPolymorphic()
         || d_function->implementingClass()->typeEntry()->isObject() ) ) { // qtd
-        s << "cast(void*) this";
-        if (arguments.count() > 0)
+        if (arg_written)
             s << ", ";
+        s << "cast(void*) this";
+        arg_written = true;
     }
 
-    if(return_in_arg) { // qtd
-        if (!d_function->isStatic() && !d_function->isConstructor()) // qtd
+    if(return_in_arg) {
+        if (arg_written)
             s << ", ";
         s << "&res";
+        arg_written = true;
     }
 
     for (int i=0; i<arguments.count(); ++i) {
@@ -805,8 +807,9 @@
         const TypeEntry *te = type->typeEntry();
 
         if (!d_function->argumentRemoved(i+1)) {
-            if (i > 0 || (!d_function->isStatic() && !d_function->isConstructor()) || return_in_arg) // qtd
+            if (arg_written)
                 s << ", ";
+            arg_written = true;
 
             // qtd
             QString modified_type = d_function->typeReplaced(arg->argumentIndex() + 1);
@@ -854,13 +857,14 @@
     }
 
     if (useJumpTable) {
-        if ((!d_function->isConstructor() && !d_function->isStatic()) || arguments.size() > 0)
+        if (arg_written)
             s << ", ";
 
         if (d_function->isStatic())
             s << "null";
         else
             s << "this";
+        arg_written = true;
     }
 
     s << ")";
@@ -1754,10 +1758,10 @@
 */
         AbstractMetaArgumentList arguments = signal->arguments();
 
-        s << "/*private extern(C) void " << sigExternName << "_handle(void* d_entity, void** args) {" << endl;
+        s << "/*private extern(C) void " << sigExternName << "_handle(void* dId, void** args) {" << endl;
         {
             Indentation indent(INDENT);
-            s << INDENT << "auto d_object = cast(" << d_class->name() << ") d_entity;" << endl;
+            s << INDENT << "auto d_object = cast(" << d_class->name() << ") dId;" << endl;
             int sz = arguments.count();
 
             for (int j=0; j<sz; ++j) {
@@ -2042,34 +2046,43 @@
         s << ">";
     }
 
+    AbstractMetaClassList interfaces = d_class->interfaces();
+    bool implements = false;
     if (!d_class->isNamespace() && !d_class->isInterface()) {
         if (!d_class->baseClassName().isEmpty()) {
             s << " : " << d_class->baseClass()->name();
+            implements = true;
         } else {
+
+            /*
             QString sc = type->defaultSuperclass();
-            if ((sc != d_class->name()) && !sc.isEmpty())
+            if ((sc != d_class->name()) && !sc.isEmpty()) {
                 s << " : " << sc;
+                implements = true;
+            }
+            */
+            if (d_class->isQObject())
+                s << " : QtdObject";
+            else
+                s << " : QtdObject";
+            implements = true;
         }
     }/* qtd else if (d_class->isInterface()) {
         s << " extends QtJambiInterface";
     }*/
 
     // implementing interfaces...
-    bool implements = false;
-    AbstractMetaClassList interfaces = d_class->interfaces();
-    if (!interfaces.isEmpty()) {
-        if (!d_class->isInterface())
+    for (int i=0; i<interfaces.size(); ++i) {
+        if (implements)
             s << ", ";
         else {
+            s << " : ";
             implements = true;
-            s << ": ";
         }
-        for (int i=0; i<interfaces.size(); ++i) {
-            AbstractMetaClass *iface = interfaces.at(i);
-            if (i) s << ", ";
-            s << iface->name();
-        }
+        AbstractMetaClass *iface = interfaces.at(i);
+        s << iface->name();
     }
+
 /* qtd
     if (isComparable(d_class)) {
         if (!implements) {
@@ -2454,7 +2467,7 @@
     }
 
     if (d_class->generateShellClass()) { // qtd2
-        if (d_class->hasVirtualFunctions()
+        if (d_class->isPolymorphic()
             && (d_class->typeEntry()->isObject() && !d_class->typeEntry()->isQObject()) )
         s << endl << "extern (C) void *__" << d_class->name() << "_entity(void *q_ptr);" << endl << endl;
     }
@@ -2557,19 +2570,19 @@
             s << INDENT << "void*[" << virtualFunctions.size() << "] virt_arr;" << endl;
             for (int pos = 0; pos<virtualFunctions.size(); ++pos) {
                 const AbstractMetaFunction *function = virtualFunctions.at(pos);
-                if (!notWrappedYet(function)) // qtd2
-                    s << INDENT << "virt_arr[" << pos << "] = &" << function->marshalledName() << "_dispatch;" <<endl;
+                if (!notWrappedYet(function) && d_class == function->declaringClass()) // qtd2
+                    s << INDENT << "virt_arr[" << pos << "] = &" << function->marshalledName(false) << "_dispatch;" <<endl;
             }
             if (virtualFunctions.size() == 0)
                 initArgs = "null";
             else
                 initArgs = "virt_arr.ptr";
 
-            if (d_class->isQObject()) {
+            if (d_class->name() == "QObject") {
                 // qt_metacall, metaObject
                 s << endl << INDENT << "void*[2] sign_arr;" << endl;
-                s << INDENT << "sign_arr[0] = &qtd_" << d_class->name() << "_qt_metacall_dispatch;" << endl;
-                s << INDENT << "sign_arr[1] = &qtd_" << d_class->name() << "_metaObject_dispatch;" << endl;
+                s << INDENT << "sign_arr[0] = &qtd_QObject_qt_metacall_dispatch;" << endl;
+                s << INDENT << "sign_arr[1] = &qtd_QObject_metaObject_dispatch;" << endl;
                 initArgs += ", sign_arr.ptr";
             }
 
@@ -2807,13 +2820,7 @@
   s << INDENT << "mixin Q_OBJECT_BIND;" << endl << endl;
 }
 
-/*
-void DGenerator::writeMarshallFunction(QTextStream &s, const AbstractMetaClass *d_class)
-{
-
-}
-*/
-void DGenerator::marshallFromCppToD(QTextStream &s, const ComplexTypeEntry* ctype)
+void DGenerator::marshalFromCppToD(QTextStream &s, const ComplexTypeEntry* ctype)
 {
     if(ctype->isQObject()) {
         QString type_name = ctype->name();
@@ -2938,13 +2945,20 @@
     Q_UNUSED(id);
     Q_UNUSED(implementor);
 
+    if (implementor != d_function->declaringClass())
+        return;
+
     s << "private extern(C) ";
-    CppImplGenerator::writeVirtualDispatchFunction(s, d_function, true);
+    CppImplGenerator::writeVirtualDispatchFunction(s, d_function, implementor, true);
     s << "{" << endl;
 
     const AbstractMetaClass *own_class = d_function->ownerClass();
 
-    s << INDENT << "auto d_object = cast(" << own_class->name() << ") d_entity;" << endl;
+    InterfaceTypeEntry *ite = own_class->typeEntry()->designatedInterface();
+    if (ite)
+        s << INDENT << "auto d_object = cast(" << ite->name() << ")cast(Object) dId;" << endl;
+    else
+        s << INDENT << "auto d_object = cast(" << own_class->name() << ") dId;" << endl;
 
     // the function arguments
     AbstractMetaArgumentList arguments = d_function->arguments();
--- a/generator/dgenerator.h	Mon May 24 23:43:30 2010 +0300
+++ b/generator/dgenerator.h	Tue May 25 17:23:11 2010 +0300
@@ -138,7 +138,7 @@
 
     void writeShellVirtualFunction(QTextStream &s, const AbstractMetaFunction *function,
                                           const AbstractMetaClass *implementor, int id);
-    void marshallFromCppToD(QTextStream &s, const ComplexTypeEntry* ctype);
+    void marshalFromCppToD(QTextStream &s, const ComplexTypeEntry* ctype);
 
 private:
     QString subDirectoryForPackage(const QString &package) const { return QString(package).replace(".", "/"); }
--- a/generator/typesystem.cpp	Mon May 24 23:43:30 2010 +0300
+++ b/generator/typesystem.cpp	Tue May 25 17:23:11 2010 +0300
@@ -1720,12 +1720,8 @@
 QString EnumTypeEntry::javaQualifier() const
 {
     TypeEntry *te = TypeDatabase::instance()->findType(m_qualifier);
-    if (te != 0) {
-        if (te->designatedInterface())
-            te = te->designatedInterface();
-
+    if (te != 0)
         return te->targetLangName();
-    }
     else
         return m_qualifier;
 }
--- a/generator/typesystem_core.xml	Mon May 24 23:43:30 2010 +0300
+++ b/generator/typesystem_core.xml	Tue May 25 17:23:11 2010 +0300
@@ -2365,13 +2365,12 @@
 
 extern "C" DLL_PUBLIC void* qtd_get_d_qobject(void *nativeId)
 {
-    QtD_QObjectEntity *entity = QtD_QObjectEntity::getQObjectEntity((QObject*)nativeId);
-    return entity ? entity-&gt;dId : NULL;
+    return QObjectEntity::getDId((QObject*)nativeId);
 }
 
 extern "C" DLL_PUBLIC void qtd_create_qobject_entity(void* nativeId, void *dId)
 {
-	new QtD_QObjectEntity((QObject*)nativeId, dId);
+	new QObjectLink((QObject*)nativeId, dId);
 }
 
 extern "C" DLL_PUBLIC void* qtd_QObject_metaObject(void* nativeId)
@@ -2379,10 +2378,11 @@
     return (void*)((QObject*)nativeId)->metaObject();
 }
 
+<!--
 extern "C" DLL_PUBLIC void qtd_connect(void* nativeId, char* signal, int id, bool dynamicEntity)
 {   
     QObject *sender = (QObject*)nativeId;
-    QObject *receiver = dynamicEntity ? dynamic_cast&lt;QObject*&gt;(QtD_QObjectEntity::getQObjectEntity(sender)) : sender;
+    QObject *receiver = dynamicEntity ? dynamic_cast&lt;QObject*&gt;(QObject::getQObjectEntity(sender)) : sender;
     const QMetaObject *mo = sender->metaObject();
     int nativeSigId = mo-&gt;indexOfSignal(signal);
     QMetaObject::connect(sender, nativeSigId, receiver, receiver-&gt;metaObject()-&gt;methodCount() + id);
@@ -2396,6 +2396,7 @@
     int nativeSigId = mo-&gt;indexOfSignal(signal);
     QMetaObject::disconnect(sender, nativeSigId, receiver, receiver-&gt;metaObject()-&gt;methodCount() + id);
 }
+-->
 
  	</inject-code>
 
--- a/include/QObjectEntity.h	Mon May 24 23:43:30 2010 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-#ifndef QQOBJECTENTITY_H
-#define QQOBJECTENTITY_H
-
-#include "qtd_core.h"
-#include <qobject.h>
-#include <iostream>
-
-QTD_EXPORT(void, qtd_delete_d_qobject, (void* dPtr))
-
-//TODO: user data ID must be registered with QObject::registerUserData;
-#define userDataId 0
-
-class QtD_QObjectEntity : public QtD_Entity, public QObjectUserData
-{
-public:
-
-    QtD_QObjectEntity(QObject *qObject, void *dId) : QtD_Entity(dId)
-    {
-        qObject->setUserData(userDataId, this);
-    }
-
-    virtual ~QtD_QObjectEntity()
-    {        
-        if (dId)
-            destroyEntity();     
-    }
-    
-    inline void destroyEntity(QObject *qObject = NULL)
-    {
-        Q_ASSERT(dId);
-        qtd_QtdObject_delete(dId);
-        if (qObject)
-        {
-            qObject->setUserData(userDataId, NULL);
-            dId = NULL;
-        }
-    }
-
-    inline static QtD_QObjectEntity* getQObjectEntity(const QObject *qObject)
-    {
-        return static_cast<QtD_QObjectEntity*>(qObject->userData(userDataId));
-    }
-};
-
-#endif // QQOBJECTENTITY_H
--- a/include/qtd_core.h	Mon May 24 23:43:30 2010 +0300
+++ b/include/qtd_core.h	Tue May 25 17:23:11 2010 +0300
@@ -1,13 +1,7 @@
 /**
-*
-*  Copyright: Copyright QtD Team, 2008-2009
-*  License: <a href="http://www.boost.org/LICENSE_1_0.txt>Boost License 1.0</a>
-*
-*  Copyright QtD Team, 2008-2009
-*  Distributed under the Boost Software License, Version 1.0.
-*  (See accompanying file boost-license-1.0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-*
-*/
+ *  Copyright: Copyright QtD Team, 2008-2010
+ *  License: Boost Software License 1.0
+ */
 
 #ifndef QTD_CORE_H
 #define QTD_CORE_H
@@ -34,6 +28,8 @@
     extern "C" TYPE NAME ARGS;
 #endif
 
+extern uint userDataId;
+
 struct QModelIndexAccessor {
 	int row;
 	int col;
@@ -54,14 +50,44 @@
     //gcManaged                 = 0x04
 };
 
-class QtD_Entity
+class DLL_PUBLIC QtdObjectLink
 {
 public:
-    void* dId;
+    void* dId; // TODO: needs to be atomic
+
+    QtdObjectLink(void* id) : dId(id) {}
+
+    template<typename T>
+    static QtdObjectLink* getLink(const T* object)
+    {
+        return dynamic_cast<QtdObjectLink*>((T*)object);
+    }
+
+    template<typename T>
+    static void* getDId(const T* object)
+    {
+        QtdObjectLink *link = getLink((T*)object);
+        return link ? link->dId : NULL;
+    }
+};
 
-    QtD_Entity(void* id) : dId(id)
+class DLL_PUBLIC QObjectLink : public QtdObjectLink, public QObjectUserData
+{
+public:
+    enum Flags
     {
-    }
+        None,
+        CreatedByD = 0x1
+    };
+
+    Flags flags;
+
+    QObjectLink(QObject* qObject, void* dId);
+    bool createdByD();
+    virtual ~QObjectLink();
+    void destroyLink(QObject* qObject = NULL);
+    static QObjectLink* getLink(const QObject* qObject);
+    static void* getDId(const QObject* qObject);
 };
 
 #define Array DArray