[Kde-bindings] playground/bindings/kimono
Arno Rehn
kde at arnorehn.de
Sat Feb 24 17:47:12 UTC 2007
SVN commit 636922 by arnorehn:
* Added ReadProperty and WriteProperty classes. Now custom properties can
be accessed via Property() and SetProperty() (and dbus?). However there seems
to be a problem with marshalling, see FIXMEs in the code. The workaround should
work as well as with marshalling, though.
* Autogeneration of Q_PROPERTY signatures and types now works properly.
* Flags of properties should now be set correctly.
CCMAIL: kde-bindings at kde.org
M +9 -0 ChangeLog
M +3 -1 Qyoto.cs
M +4 -4 QyotoMetaData.cs
M +50 -0 SmokeMarshallers.cs
M +151 -24 qyoto.cpp
M +2 -1 qyoto.h
--- trunk/playground/bindings/kimono/ChangeLog #636921:636922
@@ -1,3 +1,12 @@
+2007-02-24 Arno Rehn <arno at arnorehn.de>
+
+ * Added ReadProperty and WriteProperty classes. Now custom properties can
+ be accessed via Property() and SetProperty() (and dbus?). However there seems
+ to be a problem with marshalling, see FIXMEs in the code. The workaround should
+ work as well as with marshalling, though.
+ * Autogeneration of Q_PROPERTY signatures and types now works properly.
+ * Flags of properties should now be set correctly.
+
2007-02-21 Arno Rehn <arno at arnorehn.de>
* QMetaObjects are now correctly inherited.
--- trunk/playground/bindings/kimono/Qyoto.cs #636921:636922
@@ -555,9 +555,11 @@
Type = type;
Name = name;
}
-
+
public Q_PROPERTY()
{
+ Type = "";
+ Name = "";
}
}
}
--- trunk/playground/bindings/kimono/QyotoMetaData.cs #636921:636922
@@ -140,14 +140,14 @@
}
foreach (Qyoto.CPPProperty entry in properties) {
- PropertyFlags flags = PropertyFlags.Invalid;
+ PropertyFlags flags = PropertyFlags.StdCppSet | PropertyFlags.ResolveEditable | PropertyFlags.Stored;
if (entry.pi.CanRead && entry.pi.CanWrite) {
- flags = PropertyFlags.Readable | PropertyFlags.Writable;
+ flags |= PropertyFlags.Readable | PropertyFlags.Writable;
} else if (entry.pi.CanRead) {
- flags = PropertyFlags.Readable;
+ flags |= PropertyFlags.Readable;
} else if (entry.pi.CanWrite) {
- flags = PropertyFlags.Writable;
+ flags |= PropertyFlags.Writable;
}
if (entry.scriptable)
--- trunk/playground/bindings/kimono/SmokeMarshallers.cs #636921:636922
@@ -85,6 +85,12 @@
public static extern bool InstallGetParentMetaObject(GetIntPtr callback);
[DllImport("libqyoto", CharSet=CharSet.Ansi)]
+ public static extern bool InstallGetProperty(OverridenMethodFn callback);
+
+ [DllImport("libqyoto", CharSet=CharSet.Ansi)]
+ public static extern bool InstallSetProperty(SetPropertyFn callback);
+
+ [DllImport("libqyoto", CharSet=CharSet.Ansi)]
public static extern void InstallIntPtrToCharStarStar(GetIntPtr callback);
[DllImport("libqyoto", CharSet=CharSet.Ansi)]
@@ -160,6 +166,7 @@
public delegate void AddIntObject(IntPtr hash, int key, IntPtr val);
public delegate IntPtr DictToMap(IntPtr ptr, int type);
public delegate IntPtr ConstructDict(string type1, string type2);
+ public delegate void SetPropertyFn(IntPtr obj, string name, IntPtr variant);
#endregion
#region marshalling functions
@@ -215,7 +222,44 @@
}
return (IntPtr) GCHandle.Alloc(mo);
}
+
+ public static IntPtr GetProperty(IntPtr obj, string propertyName) {
+ object o = ((GCHandle) obj).Target;
+ Type t = o.GetType();
+ PropertyInfo pi = t.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic |
+ BindingFlags.Instance | BindingFlags.Static);
+
+ MethodInfo fromValue = typeof(QVariant).GetMethod("FromValue", BindingFlags.Public | BindingFlags.Static);
+ if (fromValue == null) throw new Exception("Couldn't find QVariant.FromValue<T> method");
+ fromValue = fromValue.MakeGenericMethod( new Type[]{ pi.PropertyType } );
+ if (pi != null) {
+ object value = pi.GetValue(o, null);
+ object[] args = { value };
+ QVariant variant = (QVariant) fromValue.Invoke(null, args);
+ return (IntPtr) GCHandle.Alloc(variant);
+ }
+
+ return (IntPtr) 0;
+ }
+
+ public static void SetProperty(IntPtr obj, string propertyName, IntPtr variant) {
+ object o = ((GCHandle) obj).Target;
+ Type t = o.GetType();
+ object v = ((GCHandle) variant).Target;
+ PropertyInfo pi = t.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic |
+ BindingFlags.Instance | BindingFlags.Static);
+
+ MethodInfo value = typeof(QVariant).GetMethod("Value", BindingFlags.Public | BindingFlags.Instance);
+ if (value == null) throw new Exception("Couldn't find QVariant.Value<T> method");
+ value = value.MakeGenericMethod( new Type[]{ pi.PropertyType } );
+
+ if (pi != null) {
+ object ret = value.Invoke(v, null);
+ pi.SetValue(o, ret, null);
+ }
+ }
+
// The key is an IntPtr corresponding to the address of the C++ instance,
// and the value is a the C# instance. This is used to prevent garbage
// collection for instances which are contained inside, and owned by
@@ -524,6 +568,9 @@
static private IsSmokeClassFn isSmokeClass = new IsSmokeClassFn(Qyoto.IsSmokeClass);
static private GetIntPtr getParentMetaObject = new GetIntPtr(GetParentMetaObject);
+ static private OverridenMethodFn getProperty = new OverridenMethodFn(GetProperty);
+ static private SetPropertyFn setProperty = new SetPropertyFn(SetProperty);
+
public static void SetUp() {
InstallFreeGCHandle(freeGCHandle);
@@ -561,6 +608,9 @@
InstallInvokeCustomSlot(invokeCustomSlot);
InstallIsSmokeClass(isSmokeClass);
InstallGetParentMetaObject(getParentMetaObject);
+
+ InstallGetProperty(getProperty);
+ InstallSetProperty(setProperty);
}
#endregion
--- trunk/playground/bindings/kimono/qyoto.cpp #636921:636922
@@ -77,6 +77,9 @@
static IsSmokeClassFn IsSmokeClass;
static GetIntPtr GetParentMetaObject;
+static OverridenMethodFn GetProperty;
+static SetPropertyFn SetProperty;
+
// Maps from a classname in the form Qt::Widget to an int id
QHash<int,char *> classname;
extern bool qRegisterResourceData(int, const unsigned char *, const unsigned char *, const unsigned char *);
@@ -852,6 +855,106 @@
}
};
+class ReadProperty : public Marshall {
+ SmokeType* _type;
+ Smoke::StackItem* _stack;
+ Smoke::StackItem* _result;
+public:
+ ReadProperty(void* obj, const char* propertyName, void** o)
+ {
+// _type = new SmokeType(qt_Smoke, qt_Smoke->idType("QVariant"));
+// _stack = new Smoke::StackItem;
+// _result = new Smoke::StackItem;
+
+ // Get the C# property value
+ void* variant = (*GetProperty)(obj, propertyName);
+// _stack->s_voidp = variant;
+
+ // FIXME
+ // doesn't work, Mono throws 'System.ArgumentException: GCHandle value belongs to a different domain'
+ // anyway, it's faster the way it's done now than with all the marshalling stuff
+// Marshall::HandlerFn fn = getMarshallFn(type());
+// (*fn)(this);
+
+ // put the marshalled value into the void* array of qt_metacall()
+ smokeqyoto_object* sqo = value_obj_info(variant);
+ o[0] = sqo->ptr; // _result->s_voidp;
+ }
+
+ SmokeType type() {
+ return *_type;
+ }
+ Marshall::Action action() { return Marshall::FromObject; }
+ Smoke::StackItem &item() { return *_stack; }
+ Smoke::StackItem &var() {
+ return *_result;
+ }
+
+ void unsupported()
+ {
+ printf("Cannot handle '%s' as property", type().name());
+ }
+ Smoke *smoke() { return type().smoke(); }
+
+ void next() {}
+
+ bool cleanup() { return false; }
+
+ ~ReadProperty() {
+// delete _stack;
+ }
+};
+
+class WriteProperty : public Marshall {
+ SmokeType* _type;
+ Smoke::StackItem* _stack;
+ Smoke::StackItem* _result;
+public:
+ WriteProperty(void* obj, const char* propertyName, void** o)
+ {
+// _type = new SmokeType(qt_Smoke, qt_Smoke->idType("QVariant"));
+ _stack = new Smoke::StackItem;
+ _result = new Smoke::StackItem;
+
+ _stack->s_voidp = o[0];
+
+ // TODO
+ // check if it works with getMarshallFn and stuff.
+ // didn't test it since it didn't work with ReadProperty
+// Marshall::HandlerFn fn = getMarshallFn(type());
+// (*fn)(this);
+
+ smokeqyoto_object* sqo = alloc_smokeqyoto_object(false, qt_Smoke, qt_Smoke->idClass("QVariant"), _stack->s_voidp);
+ void* variant = set_obj_info("Qyoto.QVariant", sqo);
+
+ // Set the C# property value
+ (*SetProperty)(obj, propertyName, variant);
+ }
+
+ SmokeType type() {
+ return *_type;
+ }
+ Marshall::Action action() { return Marshall::FromObject; }
+ Smoke::StackItem &item() { return *_stack; }
+ Smoke::StackItem &var() {
+ return *_result;
+ }
+
+ void unsupported()
+ {
+ printf("Cannot handle '%s' as property", type().name());
+ }
+ Smoke *smoke() { return type().smoke(); }
+
+ void next() {}
+
+ bool cleanup() { return false; }
+
+ ~WriteProperty() {
+// delete _stack;
+ }
+};
+
class QyotoSmokeBinding : public SmokeBinding {
public:
QyotoSmokeBinding(Smoke *s) : SmokeBinding(s) {}
@@ -1239,6 +1342,18 @@
}
void
+InstallGetProperty(OverridenMethodFn callback)
+{
+ GetProperty = callback;
+}
+
+void
+InstallSetProperty(SetPropertyFn callback)
+{
+ SetProperty = callback;
+}
+
+void
SetApplicationTerminated()
{
application_terminated = true;
@@ -1538,8 +1653,16 @@
const QMetaObject *metaobject = qobj->metaObject();
// get method count and offset
- int count = metaobject->methodCount();
- int offset = metaobject->methodOffset();
+ int count = 0;
+ int offset = 0;
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ count = metaobject->methodCount();
+ offset = metaobject->methodOffset();
+ } else {
+ count = metaobject->propertyCount();
+ offset = metaobject->propertyOffset();
+ }
+
// if id < offset call base version
if (_id < offset || (*IsSmokeClass)(obj)) {
@@ -1554,37 +1677,41 @@
i[2].s_int = _id;
i[3].s_voidp = _o;
(*fn)(m.method, o->ptr, i);
+
return i[0].s_int;
}
-
+
// Should never happen..
qFatal("Cannot find %s::qt_metacall() method\n",
o->smoke->classes[o->classId].className );
}
- // return immediately if _c != QMetaObject::InvokeMetaMethod
- if (_c != QMetaObject::InvokeMetaMethod) {
- return _id;
- }
-
- // retrieve method signature from id
- QMetaMethod method = metaobject->method(_id);
- QString name(method.signature());
- QString type(method.typeName());
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ // retrieve method signature from id
+ QMetaMethod method = metaobject->method(_id);
+ QString name(method.signature());
+ QString type(method.typeName());
+
+ if (method.methodType() == QMetaMethod::Signal) {
+ metaobject->activate(qobj, _id, (void**) _o);
+ return _id - (count - offset);
+ }
- if (method.methodType() == QMetaMethod::Signal) {
- metaobject->activate(qobj, _id, (void**) _o);
- return _id - (count - offset);
+ int items;
+ MocArgument* mocArgs = GetMocArgumentsNumber(type, name, items);
+
+ // invoke slot
+ InvokeSlot slot(obj, method.signature(), items, mocArgs, (void**)_o);
+ slot.next();
+
+ delete mocArgs;
+ } else if (_c == QMetaObject::ReadProperty) {
+ QMetaProperty property = metaobject->property(_id);
+ ReadProperty prop(obj, property.name(), (void**)_o);
+ } else if (_c == QMetaObject::WriteProperty) {
+ QMetaProperty property = metaobject->property(_id);
+ WriteProperty prop(obj, property.name(), (void**)_o);
}
-
- int items;
- MocArgument* mocArgs = GetMocArgumentsNumber(type, name, items);
-
- // invoke slot
- InvokeSlot slot(obj, method.signature(), items, mocArgs, (void**)_o);
- slot.next();
-
- delete mocArgs;
return _id - count;
}
--- trunk/playground/bindings/kimono/qyoto.h #636921:636922
@@ -76,7 +76,8 @@
typedef void (*AddInt)(void*, int);
typedef void (*AddIntObject)(void*, int, void*);
typedef void* (*DictToMap)(void*, int);
-typedef void* (*ConstructDict)(const char* type1, const char* type2);
+typedef void* (*ConstructDict)(const char*, const char*);
+typedef void (*SetPropertyFn)(void*, const char*, void*);
extern FromIntPtr FreeGCHandle;
More information about the Kde-bindings
mailing list