changeset 361:beaf4a2974d7

Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
author Max Samukha <maxter@maxter.com>
date Wed, 09 Jun 2010 11:08:56 +0300
parents 49d0a43433e7
children bcbfffef4f9e
files build/core.txt cpp/qt_core/QMetaType_shell.cpp d2/qt/core/QVariant.d d2/qtd/QMetaTypeImpl.d generator/cppimplgenerator.cpp generator/dgenerator.cpp generator/typesystem.cpp generator/typesystem.h generator/typesystem_core.xml include/qtd_core.h mini/test1/build.bat mini/test1/main.d
diffstat 12 files changed, 396 insertions(+), 179 deletions(-) [+]
line wrap: on
line diff
--- a/build/core.txt	Thu Jun 03 10:12:29 2010 +0300
+++ b/build/core.txt	Wed Jun 09 11:08:56 2010 +0300
@@ -1,19 +1,25 @@
 configure_file(d${D_VERSION}/qt/QDefines.d.inc qt/QDefines.d)
 
 ## Module specific cpp files.
-set (cpp_files qt_qtd/qtd_core qt_qtd/ArrayOpsPrimitive_shell
-    qt_core/QPoint_shell qt_core/QPointF_shell
-    qt_core/QSize_shell qt_core/QSizeF_shell
-    qt_core/QLine_shell qt_core/QLineF_shell
-    qt_core/QRect_shell qt_core/QRectF_shell
-    qt_core/QString_shell qt_core/QVariant_shell
-    qt_core/QModelIndex_shell qt_core/QMetaType_shell
+set (cpp_files
+    qt_qtd/qtd_core
+    qt_qtd/ArrayOpsPrimitive_shell
+    qt_core/QPoint_shell
+    qt_core/QPointF_shell
+    qt_core/QSize_shell
+    qt_core/QSizeF_shell
+    qt_core/QLine_shell
+    qt_core/QLineF_shell
+    qt_core/QRect_shell
+    qt_core/QRectF_shell
+    qt_core/QString_shell
+    qt_core/QVariant_shell
+    qt_core/QModelIndex_shell
     qt_core/QMetaObject_shell)
 ## Module specific d files.
 set (d_qt_files
     QGlobal
     core/QString
-    core/QMetaType
     core/QMetaObject
     core/QTypeInfo
     core/QList
@@ -34,6 +40,7 @@
     MOC
     Array
     ArrayOpsPrimitive
+    QMetaTypeImpl
     util/Tuple
     ctfe/Integer
     ctfe/String
@@ -84,5 +91,6 @@
     QXmlStreamEntityResolver
     QFileSystemWatcher
     QDynamicPropertyChangeEvent
+    QMetaType
     )
 
--- a/cpp/qt_core/QMetaType_shell.cpp	Thu Jun 03 10:12:29 2010 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-
-#include <QMetaType>
-#include "qtd_core.h"
-
-typedef void * Ctor (const void *copy);
-typedef void Dtor(void *obj);
-
-QTD_EXTERN QTD_DLL_PUBLIC int qtd_registerType(char* namePtr, Ctor ctor, Dtor dtor)
-{
-    return QMetaType::registerType(namePtr, dtor, ctor);
-}
-
-typedef void (*SaveOperator)(void *, void *);
-typedef void (*LoadOperator)(void *, void *);
-
-
-QTD_EXTERN QTD_DLL_PUBLIC void qtd_registerStreamOperators(const char *typeName, SaveOperator saveOp,
-                                        LoadOperator loadOp)
-{
-    QMetaType::registerStreamOperators(typeName, reinterpret_cast<QMetaType::SaveOperator>(saveOp),
-                                       reinterpret_cast<QMetaType::LoadOperator>(loadOp));
-}
-
-
-QTD_EXTERN QTD_DLL_PUBLIC int qtd_MetatypeId(char *id)
-{
-    return QMetaType::type(id);
-}
--- a/d2/qt/core/QVariant.d	Thu Jun 03 10:12:29 2010 +0300
+++ b/d2/qt/core/QVariant.d	Wed Jun 09 11:08:56 2010 +0300
@@ -90,45 +90,51 @@
 
 // Functions
 
-    private template getMetaId()
+    private int getMetaId(T)(string name)
     {
-	const char[] getMetaId = "
-	    int i = qtd_MetatypeId(toStringz(name));
-	    if(i <= 0)
-		i = qRegisterMetaType!(T)(name);";
+        static shared int sharedId;
+        static int id;
+        if (id == 0)
+        {
+            synchronized(qtdMoLock)
+            {
+                if (sharedId == 0)
+                    sharedId = qRegisterMetaType!T(name);
+            }
+            id = sharedId;
+        }
+        return id;
     }
 
     static public QVariant fromValue(T)(T obj)
     {
-	QVariant var;
-	static if (is(T == class) || is(T == interface))
-	{
-	    string name = obj.classinfo.name;
-	    mixin(getMetaId!());
-	    var = new QVariant(i, cast(void*)(obj));
-	}
-	else static if (isDynamicArrayType!(T) || isStaticArrayType!(T) )
-	{
-	    string name = typeid(ElementTypeOfArray!(T)).toString ~ "[]";
-	    mixin(getMetaId!());
-	    auto darray = new DArrayToC;
-	    darray.array = obj.dup;
-	    var = new QVariant(i, cast(void*)(darray));
-	}
-	else
-	{
-	    string name = typeid(T).toString;
-	    mixin(getMetaId!());
-	    auto data = new T;
-	    *data = obj;
-	    var = new QVariant(i, cast(void*)(data));
-	}
-	return var;
+        QVariant var;
+        static if (is(T == class) || is(T == interface))
+        {
+            string name = obj.classinfo.name;
+            // TODO: Still hacky. No need to pass name to id getter.
+            var = new QVariant(getMetaId!T(name), cast(void*)(obj));
+        }
+        else static if (isDynamicArrayType!(T) || isStaticArrayType!(T) )
+        {
+            string name = typeid(ElementTypeOfArray!(T)).toString ~ "[]";
+            auto darray = new DArrayToC;
+            darray.array = obj.dup;
+            var = new QVariant(getMetaId!T(name), cast(void*)(darray));
+        }
+        else
+        {
+            string name = typeid(T).toString;
+            auto data = new T;
+            *data = obj;
+            var = new QVariant(getMetaId!T(name), cast(void*)(data));
+        }
+        return var;
     }
 
     static public QVariant opCall(T)(T obj)
     {
-	return fromValue(obj);
+        return fromValue(obj);
     }
 
     public this() {
@@ -304,85 +310,87 @@
         super(__qt_return_value);
     }
 
+    // TODO: No need for run time name. Reimplement.
     private final bool canConvertImpl(string name)
     {
-	int i = qtd_MetatypeId(toStringz(name));
-	assert(i > 0);
-	return qtd_QVariant_canConvert(__nativeId, i);
+        int i = QMetaType.type(toStringz(name));
+        assert(i > 0);
+        return qtd_QVariant_canConvert(__nativeId, i);
     }
 
+    // TODO: reimplement
     public final bool canConvert(Type)() {
-	static if ( is(Type == QBitArray) )
-	    return canConvertImpl("QBitArray");
-	else static if ( is(Type == bool) )
-	    return canConvertImpl("bool");
-	else static if ( is(Type == QByteArray) )
-	    return canConvertImpl("QByteArray");
-	else static if ( is(Type == QDate) )
-	    return canConvertImpl("QDate");
-	else static if ( is(Type == QDateTime) )
-	    return canConvertImpl("QDateTime");
-	else static if ( is(Type == double) )
-	    return canConvertImpl("double");
-	else static if ( is(Type == int) )
-	    return canConvertImpl("int");
-	else static if ( is(Type == QLine) )
-	    return canConvertImpl("QLine");
-	else static if ( is(Type == QLineF) )
-	    return canConvertImpl("QLineF");
-	else static if ( is(Type == QLocale) )
-	    return canConvertImpl("QLocale");
-	else static if ( is(Type == long) )
-	    return canConvertImpl("long");
-	else static if ( is(Type == QPoint) )
-	    return canConvertImpl("QPoint");
-	else static if ( is(Type == QPointF) )
-	    return canConvertImpl("QPointF");
-	else static if ( is(Type == QRect) )
-	    return canConvertImpl("QRect");
-	else static if ( is(Type == QRectF) )
-	    return canConvertImpl("QRectF");
-	else static if ( is(Type == QRegExp) )
-	    return canConvertImpl("QRegExp");
-	else static if ( is(Type == QSize) )
-	    return canConvertImpl("QSize");
-	else static if ( is(Type == QSizeF) )
-	    return canConvertImpl("QSizeF");
-	else  static if ( is(Type == string) )
-	    return canConvertImpl("QString");
-	else  static if ( is(Type == QTime) )
-	    return canConvertImpl("QTime");
-	else static if ( is(Type == uint) )
-	    return canConvertImpl("unsigned int"); // TODO:
-	else static if ( is(Type == ulong) )
-	    return canConvertImpl("unsigned long long"); // TODO:
-	else static if ( is(Type == QUrl) )
-	    return canConvertImpl("QUrl");
-	else
-	{
-	    static if( is( Type == class ) || is( Type == interface ) )
-	    {
-		Object object = cast(Object)qtd_QVariant_data(__nativeId);
-		if(object)
-		    return cast(Type)(object) !is null;
-		return false;
-	    }
-	    else static if (isDynamicArrayType!(Type) || isStaticArrayType!(Type) )
-	    {
-		auto array = cast(DArrayToC*)qtd_QVariant_data(__nativeId);
-		return cast(Type)(array.array) !is null;
-	    }
-	    else
-	    {
-		int i = qtd_MetatypeId(toStringz(typeid(Type).toString));
-		return qtd_QVariant_canConvert(__nativeId, i);
-	    }
-	}
+        static if ( is(Type == QBitArray) )
+            return canConvertImpl("QBitArray");
+        else static if ( is(Type == bool) )
+            return canConvertImpl("bool");
+        else static if ( is(Type == QByteArray) )
+            return canConvertImpl("QByteArray");
+        else static if ( is(Type == QDate) )
+            return canConvertImpl("QDate");
+        else static if ( is(Type == QDateTime) )
+            return canConvertImpl("QDateTime");
+        else static if ( is(Type == double) )
+            return canConvertImpl("double");
+        else static if ( is(Type == int) )
+            return canConvertImpl("int");
+        else static if ( is(Type == QLine) )
+            return canConvertImpl("QLine");
+        else static if ( is(Type == QLineF) )
+            return canConvertImpl("QLineF");
+        else static if ( is(Type == QLocale) )
+            return canConvertImpl("QLocale");
+        else static if ( is(Type == long) )
+            return canConvertImpl("long");
+        else static if ( is(Type == QPoint) )
+            return canConvertImpl("QPoint");
+        else static if ( is(Type == QPointF) )
+            return canConvertImpl("QPointF");
+        else static if ( is(Type == QRect) )
+            return canConvertImpl("QRect");
+        else static if ( is(Type == QRectF) )
+            return canConvertImpl("QRectF");
+        else static if ( is(Type == QRegExp) )
+            return canConvertImpl("QRegExp");
+        else static if ( is(Type == QSize) )
+            return canConvertImpl("QSize");
+        else static if ( is(Type == QSizeF) )
+            return canConvertImpl("QSizeF");
+        else  static if ( is(Type == string) )
+            return canConvertImpl("QString");
+        else  static if ( is(Type == QTime) )
+            return canConvertImpl("QTime");
+        else static if ( is(Type == uint) )
+            return canConvertImpl("unsigned int"); // TODO:
+        else static if ( is(Type == ulong) )
+            return canConvertImpl("unsigned long long"); // TODO:
+        else static if ( is(Type == QUrl) )
+            return canConvertImpl("QUrl");
+        else
+        {
+            static if( is( Type == class ) || is( Type == interface ) )
+            {
+                Object object = cast(Object)qtd_QVariant_data(__nativeId);
+                if(object)
+                    return cast(Type)(object) !is null;
+                return false;
+            }
+            else static if (isDynamicArrayType!(Type) || isStaticArrayType!(Type) )
+            {
+                auto array = cast(DArrayToC*)qtd_QVariant_data(__nativeId);
+                return cast(Type)(array.array) !is null;
+            }
+            else
+            {
+                int i = QMetaType.type(toStringz(typeid(Type).toString));
+                return qtd_QVariant_canConvert(__nativeId, i);
+            }
+        }
     }
 
     public final Type value(Type)() {
 	static if ( is(Type == QBitArray) )
-	    return toBitArra;
+	    return toBitArray;
 	else static if ( is(Type == bool) )
 	    return toBool;
 	else static if ( is(Type == QByteArray) )
@@ -612,11 +620,11 @@
     protected override void __deleteNative() {
         qtd_QVariant_destructor(__nativeId);
     }
-    
+
     public alias void __isValueType;
 
     public alias void __isQtType_QVariant;
-    
+
     struct QTypeInfo
     {
         enum bool isComplex = true;
@@ -625,7 +633,7 @@
         enum bool isPointer = false;
         enum bool isDummy = false;
     }
-    
+
     static void* __constructNativeCopy(const void* orig) {
         return qtd_QVariant_QVariant_QVariant(cast(void*)orig);
     }
@@ -633,11 +641,11 @@
     static void* __constructPlacedNativeCopy(const void* orig, void* place) {
         return qtd_QVariant_placed_copy(orig, place);
     }
-    
+
     public static void __deleteNativeObject(void* ptr) {
         qtd_QVariant_destructor(ptr);
     }
-    
+
     public static void __callNativeDestructor(void* ptr) {
         qtd_QVariant_call_destructor(ptr);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/d2/qtd/QMetaTypeImpl.d	Wed Jun 09 11:08:56 2010 +0300
@@ -0,0 +1,141 @@
+module qtd.QMetaTypeImpl;
+
+import
+    qt.core.Qt,
+    qt.core.QDataStream,
+    qtd.QtdObject;
+
+// TODO: remove
+import std.stdio;
+
+private struct DArrayToC
+{
+    void[] array;
+}
+
+/**
+ */
+template MetaTypeOps(T)
+{
+    static void* construct(void* copy)
+    {
+        static assert (is(T : Object));
+        return cast(void*)new T(cast(T)copy);
+    }
+
+    static void destroy(void* ptr)
+    {
+        (cast(T)ptr).dispose();
+    }
+}
+
+/**
+ */
+template MetaTypeStreamOps(T)
+{
+    void save(QDataStream ds, const void* data)
+    {
+        writeln("Saving ", ds.__nativeId, " ", data);
+    }
+
+    void load(QDataStream ds, void* data)
+    {
+        writeln("Loading ", ds.__nativeId, " ", data);
+    }
+}
+
+/**
+ */
+int qRegisterMetaType(T, alias ops = MetaTypeOps)(string name = null)
+{
+    if (!name.length)
+        name = typeid(T).toString; //TODO: use compile time full name?
+
+    alias ops!T.construct construct;
+    alias ops!T.destroy destroy;
+
+    // TODO: only GNU C++
+    extern(C) static void ctorShim()
+    {
+        asm
+        {
+            naked;
+            push   EBP;
+            mov    EBP, ESP;
+            mov    EAX, 0x8[EBP];
+            call   construct;
+            leave;
+            ret;
+        }
+    }
+
+    extern(C) static void dtorShim()
+    {
+        asm
+        {
+            naked;
+            push   EBP;
+            mov    EBP, ESP;
+            mov    EAX, 0x8[EBP];
+            call   destroy;
+            leave;
+            ret;
+        }
+    }
+
+    return qtd_registerType(toStringz(name), &dtorShim, &ctorShim);
+}
+
+
+// COMPILER BUG: cannot put this inside qRegisterMetaTypeStreamOperators
+// COMPILER BUG 2: cannot use extern(C) with templated functions: extern(C) void foo(T)(){}
+private template streamOpShim(alias op)
+{
+    extern(C) void streamOpShim()
+    {
+        asm
+        {
+            naked;
+            push   EBP;
+            mov    EBP, ESP;
+            mov    EAX, 0x8[EBP];
+            push   EAX;
+            mov    EAX, 0xC[EBP];
+            call   op;
+            leave;
+            ret;
+        }
+    }
+}
+
+/**
+ */
+void qRegisterMetaTypeStreamOperators(T, alias ops = MetaTypeStreamOps)(string name = null)
+{
+    if (!name.length)
+        name = typeid(T).toString;
+
+    static void save(void* ds, const void* data)
+    {
+        scope dataStream = new QDataStream(ds, QtdObjectFlags.nativeOwnership);
+        ops!T.save(dataStream, data);
+    }
+
+    static void load(void* ds, void* data)
+    {
+        scope dataStream = new QDataStream(ds, QtdObjectFlags.nativeOwnership);
+        ops!T.load(dataStream, data);
+    }
+
+    qtd_registerStreamOperators(toStringz(name), &streamOpShim!save, &streamOpShim!load);
+}
+
+/**
+ */
+private extern(C)
+{
+    void qtd_registerStreamOperators(in char *typeName, VoidFunc saveOp, VoidFunc loadOp);
+    int qtd_registerType(in char* namePtr, VoidFunc ctor, VoidFunc dtor);
+    int qtd_QMetaType_type_nativepointerchar(in char* typeName0);
+}
+
--- a/generator/cppimplgenerator.cpp	Thu Jun 03 10:12:29 2010 +0300
+++ b/generator/cppimplgenerator.cpp	Wed Jun 09 11:08:56 2010 +0300
@@ -899,9 +899,9 @@
 
 void CppImplGenerator::writeInitCallbacks(QTextStream &s, const  AbstractMetaClass *java_class)
 {
-    QString initArgs = "pfunc_abstr *virts";
+    QString initArgs = "VoidFunc *virts";
     if (java_class->name() == "QObject")
-        initArgs += ", pfunc_abstr *sigs";
+        initArgs += ", VoidFunc *sigs";
 
     s << "QTD_EXTERN QTD_DLL_EXPORT void qtd_" << java_class->name()
       << QString("_initCallBacks(%1) {").arg(initArgs) << endl;
--- a/generator/dgenerator.cpp	Thu Jun 03 10:12:29 2010 +0300
+++ b/generator/dgenerator.cpp	Wed Jun 09 11:08:56 2010 +0300
@@ -1726,9 +1726,9 @@
 
 void DGenerator::writeFlagsSetter(QTextStream &s, const AbstractMetaClass *d_class)
 {
-    if (d_class->isInterface() || d_class->isNamespace())
+    if (d_class->isInterface())
         s << INDENT << "void __setFlags(QtdObjectFlags flags, bool val);";
-    else // COMPILER BUG:
+    else if (!d_class->isNamespace()) // COMPILER BUG:
         s << INDENT << "void __setFlags(QtdObjectFlags flags, bool val) { super.__setFlags(flags, val); }";
 }
 
@@ -1844,7 +1844,8 @@
     auxFile.isDone = true;
     auxFile.stream << "module " << auxModName << ";" << endl << endl;
 
-    bool staticInit = d_class->isQObject() || d_class->typeEntry()->isValue() || (cpp_shared && d_class->generateShellClass() && !d_class->isInterface());
+    bool staticInit = d_class->isQObject() || d_class->typeEntry()->isValue()
+                      || (cpp_shared && d_class->generateShellClass() && !d_class->isInterface() && !d_class->isNamespace());
     if (staticInit)
     {
         auxFile.isDone = false;
--- a/generator/typesystem.cpp	Thu Jun 03 10:12:29 2010 +0300
+++ b/generator/typesystem.cpp	Wed Jun 09 11:08:56 2010 +0300
@@ -779,6 +779,7 @@
         case StackElement::Include:
             attributes["file-name"] = QString();
             attributes["location"] = QString();
+            attributes["protection"] = QString();
             break;
         case StackElement::CustomMetaConstructor:
             attributes["name"] = topElement.entry->name().toLower() + "_create";
@@ -1406,13 +1407,34 @@
                     locationNames["java"] = Include::TargetLangImport;
                 }
 
+                if (locationNames.isEmpty()) {
+                    locationNames["global"] = Include::IncludePath;
+                    locationNames["local"] = Include::LocalPath;
+                    locationNames["java"] = Include::TargetLangImport;
+                }
+
                 if (!locationNames.contains(location)) {
                     m_error = QString("Location not recognized: '%1'").arg(location);
                     return false;
                 }
 
                 Include::IncludeType loc = locationNames[location];
-                Include inc(loc, attributes["file-name"]);
+
+                QString protection = attributes["protection"];
+                if (!protection.isEmpty()) {
+                    if (loc != Include::TargetLangImport) {
+                        m_error = QString("Protection attribute is allowed only if 'java' location is specified");
+                        return false;
+                    }
+
+                    if (protection != "public"
+                        || protection != "private"
+                        || protection != "package") {
+                        m_error = QString("Import protection is not recognized: '%1'").arg(protection);
+                    }
+                }
+
+                Include inc(loc, protection, attributes["file-name"]);
 
                 ComplexTypeEntry *ctype = static_cast<ComplexTypeEntry *>(element->entry);
                 if (topElement.type & StackElement::ComplexTypeEntryMask) {
@@ -1645,8 +1667,12 @@
         return "#include <" + name + '>';
     else if (type == LocalPath)
         return "#include \"" + name + "\"";
-    else
-        return "import " + name + ";";
+    else {
+        QString result;
+        if (!protection.isEmpty())
+            result += protection + " ";
+        return result + "import " + name + ";";
+    }
 }
 
 QString Modification::accessModifierString() const
--- a/generator/typesystem.h	Thu Jun 03 10:12:29 2010 +0300
+++ b/generator/typesystem.h	Wed Jun 09 11:08:56 2010 +0300
@@ -73,12 +73,21 @@
     };
 
     Include() : type(IncludePath) { }
-    Include(IncludeType t, const QString &nam) : type(t), name(nam) { };
+    Include(IncludeType t, const QString prot, const QString &nam) :
+            type(t),
+            protection(prot),
+            name(nam) { };
+
+    Include(IncludeType t, const QString &nam) :
+            type(t),
+            protection(QString()),
+            name(nam) { };
 
     bool isValid() { return !name.isEmpty(); }
 
     IncludeType type;
     QString name;
+    QString protection;
 
     QString toString() const;
 
--- a/generator/typesystem_core.xml	Thu Jun 03 10:12:29 2010 +0300
+++ b/generator/typesystem_core.xml	Wed Jun 09 11:08:56 2010 +0300
@@ -427,7 +427,6 @@
   <rejection class="QMap"/>
   <rejection class="QMapData"/>
   <rejection class="QMapIterator"/>
-  <rejection class="QMetaType"/>
   <rejection class="QMetaTypeId"/>
   <rejection class="QMetaProperty"/>
   <rejection class="QMetaObject"/>
@@ -1977,6 +1976,27 @@
   <object-type name="QTemporaryFile">
     <modify-function signature="fileName()const" rename="uniqueFilename"/>
   </object-type>
+
+  <namespace-type name="QMetaType">
+    <extra-includes>
+        <include file-name="qtd.QMetaTypeImpl" location="java" protection="public"/>
+    </extra-includes>
+
+    <inject-code class="native">
+QTD_EXTERN QTD_DLL_PUBLIC int qtd_registerType(char* namePtr, VoidFunc dtor, VoidFunc ctor)
+{
+    return QMetaType::registerType(namePtr, (QMetaType::Destructor)dtor, (QMetaType::Constructor)ctor);
+}
+
+QTD_EXTERN QTD_DLL_PUBLIC void qtd_registerStreamOperators(const char *typeName, VoidFunc saveOp,
+                                        VoidFunc loadOp)
+{
+    QMetaType::registerStreamOperators(typeName, (QMetaType::SaveOperator)saveOp,
+                                       (QMetaType::LoadOperator)loadOp);
+}
+    </inject-code>
+  </namespace-type>
+
   <object-type name="QMimeData">
     <extra-includes>
         <include file-name="QStringList" location="global"/>
--- a/include/qtd_core.h	Thu Jun 03 10:12:29 2010 +0300
+++ b/include/qtd_core.h	Wed Jun 09 11:08:56 2010 +0300
@@ -17,7 +17,7 @@
 
     #ifdef CPP_SHARED
 
-        QTD_EXTERN typedef void (*pfunc_abstr)();
+        QTD_EXTERN typedef void (*VoidFunc)();
 
         #define QTD_EXPORT_DECL(MODULE, TYPE, NAME, ARGS) \
             QTD_EXTERN typedef TYPE (*qtd_##NAME##_t)ARGS; \
@@ -25,7 +25,7 @@
 
         #define QTD_EXPORT(MODULE, NAME) \
             QTD_EXTERN { QTD_##MODULE##_DLL_PUBLIC qtd_##NAME##_t qtd_##NAME; } \
-            QTD_EXTERN QTD_DLL_EXPORT void qtd_set_##NAME(pfunc_abstr func) { qtd_##NAME = (qtd_##NAME##_t)func; }
+            QTD_EXTERN QTD_DLL_EXPORT void qtd_set_##NAME(VoidFunc func) { qtd_##NAME = (qtd_##NAME##_t)func; }
 
     #endif
 
--- a/mini/test1/build.bat	Thu Jun 03 10:12:29 2010 +0300
+++ b/mini/test1/build.bat	Wed Jun 09 11:08:56 2010 +0300
@@ -1,1 +1,2 @@
-dmd main.d libqtdcore.lib -I../../
\ No newline at end of file
+set LIB=E:\d-projects\qtd-trunk\output\build\lib
+dmd main.d ..\..\output\build\lib\qtdcore.lib -I../../d2 -I../../output/build
\ No newline at end of file
--- a/mini/test1/main.d	Thu Jun 03 10:12:29 2010 +0300
+++ b/mini/test1/main.d	Wed Jun 09 11:08:56 2010 +0300
@@ -1,31 +1,62 @@
-import qt.core.QCoreApplication;
+import qt.core.QMetaType;
+
+import std.stdio;
+import std.conv;
+import qtd.QtdObject;
+
+class A
+{
+    string name;
 
-version(Tango) { import tango.io.Stdout; } else { import std.stdio; }
+    this(A copy)
+    {
+        writeln("Creating new from ", copy.name);
+        name = "Copy of " ~ copy.name;
+    }
 
-int main(string[] args)
+    this(string name)
+    {
+        this.name = name;
+    }
+
+    void dispose()
+    {
+        writeln("Disposing ", name);
+    }
+}
+
+void main(string[] args)
 {
-    auto app = new QCoreApplication(args);
-    
-    auto parent = new QObject();
-    parent.setObjectName("papa");
-    auto child1 = new QObject(parent);
-    child1.setObjectName("child1");
-    auto child2 = new QObject(parent);
-    child2.setObjectName("child2");
-    auto child3 = new QObject(parent);
-    child3.setObjectName("child3");
-    
-    auto cd = parent.children;
-    Stdout(parent.children.length).newline;
+    int id = qRegisterMetaType!A();
+    qRegisterMetaTypeStreamOperators!A();
+
+    foreach (i; 0..10)
+    {
+        writeln("Iter ", i);
+
+        void foo(int x, int y, int z)
+        {
+            auto a = new A("A" ~ to!string(i));
+            auto b = cast(A)QMetaType.construct(id, cast(void*)a);
+            writeln(b.name);
+
+            QMetaType.destroy(id, cast(void*)a);
+            QMetaType.destroy(id, cast(void*)b);
 
-    Stdout(app.arguments).newline;
-    foreach(child; cd)
-        Stdout(child.objectName).newline;
-    
-    app.setLibraryPaths(["freakin", "bloody", "awesome!"]);
+            scope ds = new QDataStream(cast(void*)3, QtdObjectFlags.nativeOwnership);
+            QMetaType.save(ds, id, cast(void*)i);
+            QMetaType.load(ds, id, cast(void*)i);
+            writeln("Done iterating ", x, " ", y, " ", z);
+        }
 
-    Stdout(app.libraryPaths).newline;
-    
-    return 5;
-//    return app.exec();
+        foo(i + 1, i + 2, i + 3);
+    }
+    /+
+
+    writeln("Great!");
+
+
+    writeln("Even greater!");
+    +/
+
 }