2 using System.Collections;
3 using System.Runtime.InteropServices;
4 using System.Reflection.Emit;
8 namespace DBus.DBusType
13 public class Array : IDBusType
15 public const char Code = 'a';
16 private System.Array val;
17 private ArrayList elements;
18 private Type elementType;
19 private Service service = null;
25 public Array(System.Array val, Service service)
28 this.elementType = Arguments.MatchType(val.GetType().GetElementType());
29 this.service = service;
32 public Array(IntPtr iter, Service service)
34 this.service = service;
36 IntPtr arrayIter = Marshal.AllocCoTaskMem(Arguments.DBusMessageIterSize);
38 int elementTypeCode = dbus_message_iter_get_element_type (iter);
39 dbus_message_iter_recurse (iter, arrayIter);
40 this.elementType = (Type) Arguments.DBusTypes [(char) elementTypeCode];
42 elements = new ArrayList ();
44 if (dbus_message_iter_get_arg_type (arrayIter) != 0) {
46 object [] pars = new Object[2];
49 DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars);
50 elements.Add(dbusType);
51 } while (dbus_message_iter_next(arrayIter));
54 Marshal.FreeCoTaskMem(arrayIter);
57 public string GetElementCodeAsString ()
59 string ret = System.String.Empty;
60 Type t = val.GetType ().GetElementType ();
63 ret += Arguments.GetCodeAsString (Arguments.MatchType(t));
66 t = t.GetElementType ();
74 public void Append(IntPtr iter)
76 IntPtr arrayIter = Marshal.AllocCoTaskMem (Arguments.DBusMessageIterSize);
78 if (!dbus_message_iter_open_container (iter,
79 (int) Code, GetElementCodeAsString(),
81 throw new ApplicationException("Failed to append array argument: " + val);
84 foreach (object element in this.val) {
85 object [] pars = new Object[2];
87 pars[1] = this.service;
88 DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars);
89 dbusType.Append(arrayIter);
92 if (!dbus_message_iter_close_container (iter, arrayIter)) {
93 throw new ApplicationException ("Failed to append array argument: " + val);
96 Marshal.FreeCoTaskMem (arrayIter);
99 public static bool Suits(System.Type type)
101 Type type2 = type.GetElementType ();
102 if (type.IsArray || (type2 != null && type2.IsArray)) {
109 public static void EmitMarshalIn(ILGenerator generator, Type type)
112 generator.Emit(OpCodes.Ldind_Ref);
116 public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn)
118 generator.Emit(OpCodes.Castclass, type);
120 generator.Emit(OpCodes.Stind_Ref);
126 throw new ArgumentException("Cannot call Get on an Array without specifying type.");
129 public object Get(System.Type type)
132 type = type.GetElementType ();
134 if (Arguments.Suits(elementType, type.UnderlyingSystemType)) {
135 this.val = System.Array.CreateInstance(type.UnderlyingSystemType, elements.Count);
137 foreach (DBusType.IDBusType element in elements) {
138 this.val.SetValue(element.Get(type.UnderlyingSystemType), i++);
141 throw new ArgumentException("Cannot cast DBus.Type.Array to type '" + type.ToString() + "'");
147 [DllImport("dbus-1")]
148 private extern static bool dbus_message_iter_open_container (IntPtr iter,
153 [DllImport("dbus-1")]
154 private extern static bool dbus_message_iter_close_container (IntPtr iter,
157 [DllImport("dbus-1")]
158 private extern static int dbus_message_iter_get_element_type(IntPtr iter);
160 [DllImport("dbus-1")]
161 private extern static int dbus_message_iter_get_arg_type(IntPtr iter);
163 [DllImport("dbus-1")]
164 private extern static void dbus_message_iter_recurse(IntPtr iter, IntPtr subIter);
166 [DllImport("dbus-1")]
167 private extern static bool dbus_message_iter_next(IntPtr iter);
169 [DllImport("dbus-1")]
170 private extern static bool dbus_message_iter_has_next (IntPtr iter);