[Kde-bindings] playground/bindings/kimono
Richard Dale
Richard_Dale at tipitina.demon.co.uk
Mon May 29 20:05:10 UTC 2006
SVN commit 546351 by rdale:
* More fixes from Paulo:
* To avoid virtual method dispatch resulting in infinite loop, the
meta object instance is now created in c++ code using smoke (just as
in qtruby).
* Qyoto.GetMetaObject now works for Qt types as well
* Decommented code in set_obj_info. This function is used by the
return value marshaller for non-primitive types and by
make_metaObject.
CCMAIL: kde-bindings at kde.org
M +9 -0 ChangeLog
M +1 -1 SmokeInvocation.cs
M +42 -33 qyoto.cpp
M +36 -34 qyoto/Qyoto.cs
--- trunk/playground/bindings/kimono/ChangeLog #546350:546351
@@ -1,5 +1,14 @@
2006-05-29 Richard Dale <rdale at foton.es>
+ * More fixes from Paulo:
+ * To avoid virtual method dispatch resulting in infinite loop, the
+ meta object instance is now created in c++ code using smoke (just as
+ in qtruby).
+ * Qyoto.GetMetaObject now works for Qt types as well
+ * Decommented code in set_obj_info. This function is used by the
+ return value marshaller for non-primitive types and by
+ make_metaObject.
+
* Added patch from Paulo Capriotti to create a QMetaObject at runtime
for a Qyoto class with custom slots and/or signals
--- trunk/playground/bindings/kimono/SmokeInvocation.cs #546350:546351
@@ -200,7 +200,7 @@
Type klass = Type.GetType(className);
Type[] constructorParamTypes = new Type[1];
- constructorParamTypes[0] = Type.GetType("System.Type");
+ constructorParamTypes[0] = typeof(Type);
ConstructorInfo constructorInfo = klass.GetConstructor(BindingFlags.NonPublic
| BindingFlags.Instance, null, new Type[ ] { typeof( Type ) } , null);
if (constructorInfo == null) {
--- trunk/playground/bindings/kimono/qyoto.cpp #546350:546351
@@ -49,7 +49,7 @@
#include "smoke.h"
#define QYOTO_VERSION "0.0.1"
-// #define DEBUG
+#define DEBUG
extern Smoke *qt_Smoke;
extern void init_qt_Smoke();
@@ -164,10 +164,9 @@
void *
set_obj_info(const char * className, smokeqyoto_object * o)
{
-// void * obj = (*CreateInstance)(className);
-// (*SetSmokeObject)(obj, o);
-// return obj;
- return 0;
+ void * obj = (*CreateInstance)(className);
+ (*SetSmokeObject)(obj, o);
+ return obj;
}
Marshall::HandlerFn getMarshallFn(const SmokeType &type);
@@ -942,11 +941,8 @@
strcmp(m.signature(), signatureStr) == 0)
break;
}
-
-#ifdef DEBUG
+
printf("emitting signal %d\n", i);
-#endif
-
EmitSignal signal(qobj, i, items, args, sp);
signal.next();
@@ -958,32 +954,45 @@
}
-void *
-make_metaObject(QMetaObject* parent, const char* stringdata, const uint* data) {
-#ifdef DEBUG
- printf("parent = %x\n", parent);
+void* make_metaObject(void* obj, const char* stringdata, const uint* data) {
printf("stringdata = %s\n", stringdata);
printf("data = %x\n", data);
-#endif
- // create a QMetaObject on the stack
- QMetaObject tmp = {{
- parent,
- stringdata,
- data,
- 0
- }};
-
- // copy it to the heap
- QMetaObject* meta = new QMetaObject;
- *meta = tmp;
-
- // create smoke object
- smokeqyoto_object* m = (smokeqyoto_object*)malloc(sizeof(smokeqyoto_object));
- m->smoke = qt_Smoke;
- m->classId = qt_Smoke->idClass("QMetaObject");
- m->ptr = meta;
-
- return m;
+
+ smokeqyoto_object* o = value_obj_info(obj);
+ Smoke::Index nameId = o->smoke->idMethodName("metaObject");
+ Smoke::Index meth = o->smoke->findMethod(o->classId, nameId);
+ if (meth <= 0) {
+ // Should never happen..
+ 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);
+
+ QMetaObject* parent = (QMetaObject*) i[0].s_voidp;
+
+ // create a QMetaObject on the stack
+ QMetaObject tmp = {{
+ parent,
+ stringdata,
+ data,
+ 0
+ }};
+
+ // copy it to the heap
+ QMetaObject* meta = new QMetaObject;
+ *meta = tmp;
+
+ // create smoke object
+ smokeqyoto_object* m = (smokeqyoto_object*)malloc(sizeof(smokeqyoto_object));
+ m->smoke = qt_Smoke;
+ m->classId = qt_Smoke->idClass("QMetaObject");
+ m->ptr = meta;
+
+ // create wrapper C# instance
+ return set_obj_info("Qt.QMetaObject", m);
}
void
--- trunk/playground/bindings/kimono/qyoto/Qyoto.cs #546350:546351
@@ -21,7 +21,7 @@
/// This hashtable has classe names as keys, and QMetaObjects as values
static Hashtable metaObjects = new Hashtable();
- public static void GetSlotSignatures(Type t) {
+ public static Hashtable GetSlotSignatures(Type t) {
/// Remove the old object if it already exists
classes.Remove(t.Name);
@@ -40,6 +40,7 @@
}
classes.Add(t.Name, slots);
+ return slots;
}
public static string[] GetSignalSignatures(Type t) {
@@ -174,61 +175,62 @@
}
}
- public static QMetaObject MakeMetaObject(Type t) {
-#if DEBUG
- Console.WriteLine("ENTER: MakeMetaObject. t => {0}", t);
-#endif
+ public static QMetaObject MakeMetaObject(Type t, QObject o) {
+ if (t == null) return null;
- if (t == null || typeof(QObject).IsAssignableFrom(t)) return null;
-
string className = t.ToString();
Hashtable slotTable = (Hashtable)classes[className];
+
ICollection slots;
if (slotTable != null)
slots = slotTable.Values;
else {
// build slot table
- GetSlotSignatures(t);
- slotTable = (Hashtable)classes[className];
- slots = slotTable.Values;
+ slots = GetSlotSignatures(t).Values;
}
-
+
string[] signals = GetSignalSignatures(t);
QyotoMetaData metaData = new QyotoMetaData(className, signals, slots);
- GCHandle parentMetaObject = GCHandle.Alloc(GetMetaObject(t.BaseType));
- IntPtr metaSmokeObject;
-
+
+ GCHandle objHandle = GCHandle.Alloc(o);
+ IntPtr metaObject;
+
unsafe {
fixed (byte* stringdata = metaData.StringData)
fixed (int* data = metaData.Data) {
- metaSmokeObject = make_metaObject((IntPtr)parentMetaObject, (IntPtr)stringdata, (IntPtr)data);
+ metaObject = make_metaObject((IntPtr)objHandle, (IntPtr)stringdata, (IntPtr)data);
}
}
- // create a new C# QMetaObject and replace its
- // inner _smokeObject with that returned from make_metaObject
- QMetaObject res = new QMetaObject();
- FieldInfo fieldInfo = typeof(QMetaObject).GetField( "_smokeObject",
- BindingFlags.NonPublic
- | BindingFlags.GetField
- | BindingFlags.Instance );
- ((GCHandle)fieldInfo.GetValue(res)).Free();
- fieldInfo.SetValue(res, metaSmokeObject);
-
-#if DEBUG
- Console.WriteLine("LEAVE MakeMetaObject");
-#endif
+ QMetaObject res = (QMetaObject)((GCHandle) metaObject).Target;
return res;
}
- public static QMetaObject GetMetaObject(Type t) {
- QMetaObject res = (QMetaObject)metaObjects[t.ToString()];
- if (res == null) {
- res = MakeMetaObject(t);
- metaObjects[t.ToString()] = res;
+ public static QMetaObject GetMetaObject(Type t, QObject o) {
+ object[] attr = t.GetCustomAttributes(typeof(SmokeClass), false);
+ if (attr.Length > 0) {
+ // qt class: simply call the MetaObject method
+ MethodInfo metaObjectMethod = t.GetMethod("MetaObject", BindingFlags.Public | BindingFlags.Instance);
+ if (metaObjectMethod == null) {
+ // this should never happen
+ Console.WriteLine("** Cannot find MetaObject method **");
+ return null;
+ }
+ else {
+ return (QMetaObject)metaObjectMethod.Invoke(o, new object[] {});
+ }
}
- return res;
+ else {
+ // user defined class: retrieve QMetaObject from the hashtable
+ QMetaObject res = (QMetaObject)metaObjects[t.ToString()];
+ if (res == null) {
+ // create QMetaObject
+ res = MakeMetaObject(t, o);
+ metaObjects[t.ToString()] = res;
+ }
+ return res;
+ }
}
}
More information about the Kde-bindings
mailing list