[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