[Kde-bindings] playground/bindings/kimono

Richard Dale rdale at foton.es
Tue Feb 27 08:28:00 UTC 2007


On Monday 26 February 2007, Arno Rehn wrote:
> > [   cut   ]
>
> Ok, I found out why QDBusAbstractAdaptor doesn't work with the current way
> of implementation. It seems like a call to 'staticMetaObject' via Smoke
> doesn't return the same meta object as we would get when calling
> QDBusAbstractAdaptor::staticMetaObject - I don't know what's going wrong
> there, but the returned object is definitely an other one. I compared the
> return value of meta->superClass() with
> &QDBusAbstractAdaptor::staticMetaObject at the end of make_metaObject() in
> both the revision of Qyoto in which it still worked and in the current one.
> With the revision where it still worked, the pointers were the same,
> currently they aren't.
> The workaround itself is rather simple, look for the line
> 	QMetaObject* parent = parent_meta_object(type);
> in make_metaObject() and directly after that add
> 	if (strcmp(parent->className(), "QDBusAbstractAdaptor") == 0) {
> 		parent = (QMetaObject*) &QDBusAbstractAdaptor::staticMetaObject;
> 	}
> and voila, it should work.
Yes staticMetaObject is a value type and the smoke lib code makes a copy of 
value type return values. I'm not sure that it needs to make copies of static 
value typed variables too, but current it does. Here is the code generated 
for the staticMetaObject accessor for QDBusAbstractAdaptor:

class x_QDBusAbstractAdaptor : public QDBusAbstractAdaptor {
public:
    static void x_0(Smoke::Stack x) {
        x[0].s_class = (void*)new 
QMetaObject(QDBusAbstractAdaptor::staticMetaObject);
    }
...


> At least kind of, there still seem to be some 
> problems with QDBusVariants...
Yes, marshalling QDBusVariants doesn't work in QtRuby either yet for reasons 
which I haven't worked out. In ruby the complexpong query() slot gets called, 
but the QDBusVariant is always null. In Qyoto before your change to using 
staticMetaObject instead of metaObject() on the instance, the query() slot 
was never called.

Here is how I think parent_meta_object() and make_metaObject() should be:

QMetaObject* parent_meta_object(void* obj) {
    smokeqyoto_object* o = value_obj_info(obj);
    Smoke::Index nameId = o->smoke->idMethodName("metaObject");
    Smoke::Index parent_index = o->smoke->classes[o->classId].parents;
    if (!parent_index)
        return 0;

    Smoke::Index parentId = o->smoke->inheritanceList[parent_index];
    Smoke::Index meth = o->smoke->findMethod(parentId, nameId);
    if (meth <= 0)
        return 0;
        
    Smoke::Method &methodId = 
o->smoke->methods[o->smoke->methodMaps[meth].method];
    Smoke::ClassFn fn = o->smoke->classes[methodId.classId].classFn;
    Smoke::StackItem i[1];
    (*fn)(methodId.method, o->ptr, i);
    
    return (QMetaObject*) i[0].s_voidp;
}

void* make_metaObject(    void* obj, void* parentMeta, 
                        const char* stringdata, int stringdata_count, 
                        const uint* data, int data_count ) 
{
    QMetaObject* parent = 0;

    if (parentMeta == 0) {
        // The parent class is a Smoke class, so call metaObject() on the
        // instance to get it via a smoke library call
        parent = parent_meta_object(obj);
    } else {
        // The parent class is a custom C# class whose metaObject
        // was constructed at runtime
	    smokeqyoto_object* o = value_obj_info(parentMeta);
	    parent = o->ptr;
    }

    char* my_stringdata = new char[stringdata_count];
    memcpy(my_stringdata, stringdata, stringdata_count * sizeof(char));
    
    uint* my_data = new uint[data_count];
    memcpy(my_data, data, data_count * sizeof(uint));
    
    // create a QMetaObject on the stack
    QMetaObject tmp = {{
        parent,
        my_stringdata,
        my_data,
        0
    }};
    ...

If we don't want to construct a QMetaObject at runtime we should never call 
make_metaObject() in the first place.

> I don't know why this problem exists or why it is important 'which' meta
> object is set as a parent, because the signals/slots/classinfos/whatever
> are the same since it is a native Qt class and not a custom one created in
> C#. Is there another way to obtain the static metaobject of an object than
> reading staticMetaObject? I don't want to create an instance of every
> parent class to pass to make_metaObject() as it would slow down the whole
> thing a lot, as I've already said.
> Any ideas?
We don't have to make new instances, we just need to pass the original 
instance on which metaObject() was called, and optionally its parent 
QMetaObject as above.

In the C# side when a metaObject() is requested for a custom C# subclass of a 
SmokeClass: 

Look up the entry in the dictionary of classname vs. runtime created 
MetaObjects. If present return that.

If the parent class is a Smoke class call make_metaObject() with the parent 
arg of 0.

If the parent class is a custom C# class create its QMetaObject first to use 
as a parent. If needed, call recursively with the C# superclass until we get 
to the C# class whose immediate superclass is a Smoke Class and call 
make_metaObject() for that with an arg for parent metaobject of 0.

-- Richard



More information about the Kde-bindings mailing list