summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOwen Fraser-Green <owen@discobabe.net>2004-03-23 12:10:32 +0000
committerOwen Fraser-Green <owen@discobabe.net>2004-03-23 12:10:32 +0000
commitc916037773d7d3d8d37ca2c5a8899b7b728e377d (patch)
tree21c37372ab9795583e724e8459578b7fe0be330b
parent2195cf0dbde2ae26b5a684c6d914c1711f44c28d (diff)
First checkin of the Mono bindings.
-rw-r--r--ChangeLog9
-rw-r--r--Makefile.am9
-rw-r--r--configure.in4
-rw-r--r--dbus-sharp.pc.in8
-rw-r--r--mono/Arguments.cs304
-rw-r--r--mono/Bus.cs51
-rw-r--r--mono/Connection.cs310
-rw-r--r--mono/Custom.cs18
-rw-r--r--mono/DBus.cs24
-rw-r--r--mono/DBusException.cs12
-rw-r--r--mono/DBusType/Array.cs130
-rw-r--r--mono/DBusType/Boolean.cs86
-rw-r--r--mono/DBusType/Byte.cs86
-rw-r--r--mono/DBusType/Custom.cs109
-rw-r--r--mono/DBusType/Dict.cs145
-rw-r--r--mono/DBusType/Double.cs86
-rw-r--r--mono/DBusType/IDBusType.cs16
-rw-r--r--mono/DBusType/Int32.cs86
-rw-r--r--mono/DBusType/Int64.cs86
-rw-r--r--mono/DBusType/Nil.cs68
-rw-r--r--mono/DBusType/ObjectPath.cs110
-rw-r--r--mono/DBusType/String.cs86
-rw-r--r--mono/DBusType/UInt32.cs87
-rw-r--r--mono/DBusType/UInt64.cs87
-rw-r--r--mono/Error.cs53
-rw-r--r--mono/Handler.cs256
-rw-r--r--mono/InterfaceAttribute.cs23
-rw-r--r--mono/Introspector.cs106
-rw-r--r--mono/Makefile.am40
-rw-r--r--mono/Message.cs419
-rw-r--r--mono/MethodAttribute.cs12
-rw-r--r--mono/MethodCall.cs80
-rw-r--r--mono/MethodReturn.cs57
-rw-r--r--mono/ProxyBuilder.cs301
-rw-r--r--mono/README118
-rw-r--r--mono/Server.cs148
-rw-r--r--mono/Service.cs115
-rw-r--r--mono/Signal.cs60
-rw-r--r--mono/TODO8
-rw-r--r--mono/Test.cs93
-rw-r--r--mono/example/EchoClient.cs19
-rw-r--r--mono/example/EchoServer.cs23
-rw-r--r--mono/example/Echoer.cs16
-rw-r--r--mono/example/Makefile.am19
44 files changed, 3646 insertions, 337 deletions
diff --git a/ChangeLog b/ChangeLog
index 194549e8..30ae5ad3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2004-03-23 Owen Fraser-Green <owen@discobabe.net>
+
+ First checkin of mono bindings.
+
+ * configure.in:
+ * Makefile.am:
+ Build stuff for the bindings
+ * dbus-sharp.pc.in: Added for pkgconfig
+
2004-03-21 Havoc Pennington <hp@redhat.com>
* test/test-service.c (main): remove debug spew
diff --git a/Makefile.am b/Makefile.am
index 82fee346..aa6f0ecd 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,6 +14,7 @@ endif
if DBUS_USE_MCS
MONO_SUBDIR=mono
+ MONO_PC=dbus-sharp.pc
endif
if HAVE_PYTHON
@@ -30,16 +31,18 @@ dist-local:
SUBDIRS=dbus bus doc $(GLIB_SUBDIR) $(GCJ_SUBDIR) $(MONO_SUBDIR) $(QT_SUBDIR) $(PYTHON_SUBDIR) test tools
pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = dbus-1.pc $(GLIB_PC)
+pkgconfig_DATA = dbus-1.pc $(GLIB_PC) $(MONO_PC)
DISTCLEANFILES = \
dbus-1.pc \
- $(GLIB_PC)
+ $(GLIB_PC) \
+ $(MONO_PC)
EXTRA_DIST = \
HACKING \
dbus-1.pc.in \
- dbus-glib-1.pc.in
+ dbus-glib-1.pc.in \
+ dbus-sharp.pc.in
all-local: Doxyfile
diff --git a/configure.in b/configure.in
index 5612f301..e92fdb14 100644
--- a/configure.in
+++ b/configure.in
@@ -35,7 +35,7 @@ AC_ARG_ENABLE(doxygen-docs, [ --enable-doxygen-docs build DOXYGEN docum
AC_ARG_ENABLE(gcov, [ --enable-gcov compile with coverage profiling instrumentation (gcc only)],enable_gcov=$enableval,enable_gcov=no)
AC_ARG_ENABLE(abstract-sockets, [ --enable-abstract-sockets use abstract socket namespace (linux only)],enable_abstract_sockets=$enableval,enable_abstract_sockets=auto)
AC_ARG_ENABLE(gcj, [ --enable-gcj build gcj bindings],enable_gcj=$enableval,enable_gcj=no)
-AC_ARG_ENABLE(mono, [ --enable-mono build mono bindings],enable_mono=$enableval,enable_mono=no)
+AC_ARG_ENABLE(mono, [ --enable-mono build mono bindings],enable_mono=$enableval,enable_mono=auto)
AC_ARG_ENABLE(python, [ --enable-python build python bindings],enable_python=$enableval,enable_python=auto)
@@ -1022,6 +1022,7 @@ gcj/org/Makefile
gcj/org/freedesktop/Makefile
gcj/org/freedesktop/dbus/Makefile
mono/Makefile
+mono/example/Makefile
bus/Makefile
tools/Makefile
test/Makefile
@@ -1090,6 +1091,7 @@ echo "
Building Qt bindings: ${have_qt}
Building GLib bindings: ${have_glib}
Building Python bindings: ${have_python}
+ Building Mono bindings: ${enable_mono}
Building GTK+ tools: ${have_gtk}
Building X11 code: ${enable_x11}
Building Doxygen docs: ${enable_doxygen_docs}
diff --git a/dbus-sharp.pc.in b/dbus-sharp.pc.in
new file mode 100644
index 00000000..c6b7044c
--- /dev/null
+++ b/dbus-sharp.pc.in
@@ -0,0 +1,8 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+
+Name: DBus#
+Description: DBus# - D-BUS .NET Bindings
+Version: 0.1
+
diff --git a/mono/Arguments.cs b/mono/Arguments.cs
new file mode 100644
index 00000000..ac88d6a7
--- /dev/null
+++ b/mono/Arguments.cs
@@ -0,0 +1,304 @@
+using System;
+using System.Collections;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+namespace DBus
+{
+ // Holds the arguments of a message. Provides methods for appending
+ // arguments and to assist in matching .NET types with D-BUS types.
+ public class Arguments : IEnumerable
+ {
+ // Must follow sizeof(DBusMessageIter)
+ internal const int DBusMessageIterSize = 14*4;
+ private static Hashtable dbusTypes = null;
+ private Message message;
+ private IntPtr appenderIter = Marshal.AllocCoTaskMem(DBusMessageIterSize);
+ private IEnumerator enumerator = null;
+
+ internal Arguments()
+ {
+ }
+
+ ~Arguments()
+ {
+ Marshal.FreeCoTaskMem(appenderIter);
+ }
+
+ internal Arguments(Message message)
+ {
+ this.message = message;
+ }
+
+ // Checks the suitability of a D-BUS type for supporting a .NET
+ // type.
+ public static bool Suits(Type dbusType, Type type)
+ {
+ object [] pars = new object[1];
+ pars[0] = type;
+
+ return (bool) dbusType.InvokeMember("Suits", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, pars, null);
+ }
+
+ // Find a suitable match for the given .NET type or throw an
+ // exception if one can't be found.
+ public static Type MatchType(Type type)
+ {
+ foreach(Type dbusType in DBusTypes.Values) {
+ if (Suits(dbusType, type)) {
+ return dbusType;
+ }
+ }
+
+ throw new ApplicationException("No suitable DBUS type found for type '" + type + "'");
+ }
+
+ // The D-BUS types.
+ public static Hashtable DBusTypes {
+ get
+ {
+ if (dbusTypes == null) {
+ dbusTypes = new Hashtable();
+
+ foreach (Type type in Assembly.GetAssembly(typeof(DBusType.IDBusType)).GetTypes()) {
+ if (type != typeof(DBusType.IDBusType) && typeof(DBusType.IDBusType).IsAssignableFrom(type)) {
+ dbusTypes.Add(GetCode(type), type);
+ }
+ }
+ }
+
+ return dbusTypes;
+ }
+ }
+
+ // Append an argument
+ public void Append(DBusType.IDBusType dbusType)
+ {
+ if (dbusType.GetType() == typeof(DBusType.ObjectPath)) {
+ ((DBusType.ObjectPath) dbusType).SetService(message.Service);
+ }
+ dbusType.Append(appenderIter);
+ }
+
+ // Append an argument of the specified type
+ private void AppendType(Type type, object val)
+ {
+ object [] pars = new Object[1];
+ pars[0] = val;
+ DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(MatchType(type), pars);
+ Append(dbusType);
+ }
+
+ // Append the results of a method call
+ public void AppendResults(MethodInfo method, object retVal, object [] parameters)
+ {
+ InitAppending();
+
+ if (method.ReturnType != typeof(void)) {
+ AppendType(method.ReturnType, retVal);
+ }
+
+ for (int i = 0; i < method.GetParameters().Length; i++) {
+ ParameterInfo par = method.GetParameters()[i];
+ if (par.IsOut || par.ParameterType.ToString().EndsWith("&")) {
+ // It's an OUT or INOUT parameter.
+ AppendType(par.ParameterType.UnderlyingSystemType, parameters[i]);
+ }
+ }
+ }
+
+ // Get the parameters
+ public object[] GetParameters(MethodInfo method)
+ {
+ ParameterInfo[] pars = method.GetParameters();
+ ArrayList paramList = new ArrayList();
+
+ enumerator = GetEnumerator();
+ foreach (ParameterInfo par in pars) {
+ if (!par.IsOut) {
+ // It's an IN or INOUT paramter.
+ enumerator.MoveNext();
+ DBusType.IDBusType dbusType = (DBusType.IDBusType) enumerator.Current;
+ paramList.Add(dbusType.Get(par.ParameterType));
+ } else {
+ // It's an OUT so just create a parameter for it
+ object var = null;
+ paramList.Add(var);
+ }
+ }
+
+ return paramList.ToArray();
+ }
+
+ // Parse the IN & REF parameters to a method and return the types in a list.
+ public static object[] ParseInParameters(MethodInfo method)
+ {
+ ArrayList types = new ArrayList();
+
+ ParameterInfo[] pars = method.GetParameters();
+ foreach (ParameterInfo par in pars) {
+ if (!par.IsOut) {
+ types.Add(MatchType(par.ParameterType));
+ }
+ }
+
+ return types.ToArray();
+ }
+
+ // Parse the OUT & REF parameters to a method and return the types in a list.
+ public static object[] ParseOutParameters(MethodInfo method)
+ {
+ ArrayList types = new ArrayList();
+
+ ParameterInfo[] pars = method.GetParameters();
+ foreach (ParameterInfo par in pars) {
+ if (par.IsOut || par.ParameterType.ToString().EndsWith("&")) {
+ types.Add(MatchType(par.ParameterType));
+ }
+ }
+
+ return types.ToArray();
+ }
+
+ // Get the appropriate constructor for a D-BUS type
+ public static ConstructorInfo GetDBusTypeConstructor(Type dbusType, Type type)
+ {
+ ConstructorInfo constructor = dbusType.GetConstructor(new Type[] {type.UnderlyingSystemType});
+ if (constructor == null)
+ throw new ArgumentException("There is no valid constructor for '" + dbusType + "' from type '" + type + "'");
+
+ return constructor;
+ }
+
+ // Get the signature of a method
+ public static string ParseParameters(MethodInfo method)
+ {
+ ParameterInfo[] pars = method.GetParameters();
+ string key = "";
+
+ foreach (ParameterInfo par in pars) {
+ if (!par.IsOut) {
+ Type dbusType = MatchType(par.ParameterType);
+ key += GetCode(dbusType);
+ }
+ }
+
+ return key;
+ }
+
+ // Get the type code for a given D-BUS type
+ public static char GetCode(Type dbusType)
+ {
+ return (char) dbusType.InvokeMember("Code", BindingFlags.Static | BindingFlags.GetField, null, null, null);
+ }
+
+ // Get a complete method signature
+ public override string ToString()
+ {
+ IntPtr iter = Marshal.AllocCoTaskMem(DBusMessageIterSize);
+ string key = "";
+
+ // Iterate through the parameters getting the type codes to a string
+ dbus_message_iter_init(message.RawMessage, iter);
+
+ do {
+ char code = (char) dbus_message_iter_get_arg_type(iter);
+ if (code == '\0')
+ return key;
+
+ key += code;
+ } while (dbus_message_iter_next(iter));
+
+ Marshal.FreeCoTaskMem(iter);
+
+ return key;
+ }
+
+ // Move to the next parameter
+ public DBusType.IDBusType GetNext()
+ {
+ enumerator.MoveNext();
+ return (DBusType.IDBusType) enumerator.Current;
+ }
+
+ // Begin appending
+ public void InitAppending()
+ {
+ dbus_message_append_iter_init(message.RawMessage, appenderIter);
+ }
+
+ // Get the enumerator
+ public IEnumerator GetEnumerator()
+ {
+ return new ArgumentsEnumerator(this);
+ }
+
+ private class ArgumentsEnumerator : IEnumerator
+ {
+ private Arguments arguments;
+ private bool started = false;
+ private IntPtr iter = Marshal.AllocCoTaskMem(Arguments.DBusMessageIterSize);
+
+ public ArgumentsEnumerator(Arguments arguments)
+ {
+ this.arguments = arguments;
+ Reset();
+ }
+
+ ~ArgumentsEnumerator()
+ {
+ Marshal.FreeCoTaskMem(iter);
+ }
+
+ public bool MoveNext()
+ {
+ if (started) {
+ return dbus_message_iter_next(iter);
+ } else {
+ started = true;
+ return true;
+ }
+ }
+
+ public void Reset()
+ {
+ dbus_message_iter_init(arguments.message.RawMessage, iter);
+ started = false;
+ }
+
+ public object Current
+ {
+ get
+ {
+ object [] pars = new Object[1];
+ pars[0] = iter;
+
+ Type type = (Type) DBusTypes[(char) dbus_message_iter_get_arg_type(iter)];
+ DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(type, pars);
+
+ // Special case for ObjectPath
+ if (type == typeof(DBusType.ObjectPath)) {
+ ((DBusType.ObjectPath) dbusType).SetService(arguments.message.Service);
+ }
+
+ return dbusType;
+ }
+ }
+ }
+
+ [DllImport("dbus-1")]
+ private extern static void dbus_message_append_iter_init(IntPtr rawMessage, IntPtr iter);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_has_next(IntPtr iter);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_next(IntPtr iter);
+
+ [DllImport("dbus-1")]
+ private extern static void dbus_message_iter_init(IntPtr rawMessage, IntPtr iter);
+
+ [DllImport("dbus-1")]
+ private extern static int dbus_message_iter_get_arg_type(IntPtr iter);
+ }
+}
diff --git a/mono/Bus.cs b/mono/Bus.cs
new file mode 100644
index 00000000..963e8195
--- /dev/null
+++ b/mono/Bus.cs
@@ -0,0 +1,51 @@
+namespace DBus
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics;
+
+ public class Bus
+ {
+ // Keep in sync with C
+ private enum BusType
+ {
+ Session = 0,
+ System = 1,
+ Activation = 2
+ }
+
+ public static Connection GetSessionBus()
+ {
+ return GetBus(BusType.Session);
+ }
+
+ public static Connection GetSystemBus()
+ {
+ return GetBus(BusType.System);
+ }
+
+ private static Connection GetBus(BusType busType)
+ {
+ Error error = new Error();
+ error.Init();
+
+ IntPtr rawConnection = dbus_bus_get((int) busType, ref error);
+
+ if (rawConnection != IntPtr.Zero) {
+ Connection connection = Connection.Wrap(rawConnection);
+ connection.SetupWithMain();
+ dbus_connection_unref(rawConnection);
+
+ return connection;
+ } else {
+ throw new DBusException(error);
+ }
+ }
+
+ [DllImport ("dbus-1")]
+ private extern static IntPtr dbus_bus_get (int which, ref Error error);
+
+ [DllImport ("dbus-1")]
+ private extern static void dbus_connection_unref (IntPtr ptr);
+ }
+}
diff --git a/mono/Connection.cs b/mono/Connection.cs
index 56dcb7a2..406e779b 100644
--- a/mono/Connection.cs
+++ b/mono/Connection.cs
@@ -1,192 +1,180 @@
-namespace DBus {
+namespace DBus
+{
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
+ using System.Reflection;
+ using System.IO;
+ using System.Collections;
- public class Connection {
+ public class Connection
+ {
+ /// <summary>
+ /// A pointer to the underlying Connection structure
+ /// </summary>
+ private IntPtr rawConnection;
+
+ /// <summary>
+ /// The current slot number
+ /// </summary>
+ private static int slot = -1;
+
+ private int timeout = -1;
- public Connection (string address) {
+ internal Connection(IntPtr rawConnection)
+ {
+ RawConnection = rawConnection;
+ }
+
+ public Connection(string address)
+ {
// the assignment bumps the refcount
- Error error = new Error ();
- error.Init ();
- raw = dbus_connection_open (address, ref error);
- if (raw != IntPtr.Zero) {
- dbus_connection_unref (raw);
+ Error error = new Error();
+ error.Init();
+ RawConnection = dbus_connection_open(address, ref error);
+ if (RawConnection != IntPtr.Zero) {
+ dbus_connection_unref(RawConnection);
} else {
- Exception e = new Exception (ref error);
- error.Free ();
- throw e;
+ throw new DBusException(error);
}
- dbus_connection_setup_with_g_main (raw, IntPtr.Zero);
- }
- // Keep in sync with C
- public enum BusType {
- Session = 0,
- System = 1,
- Activation = 2
+ SetupWithMain();
}
- public static Connection GetBus (BusType bus) {
- Error error = new Error ();
-
- error.Init ();
-
- IntPtr ptr = dbus_bus_get ((int) bus, ref error);
- if (ptr != IntPtr.Zero) {
- Connection c = Wrap (ptr);
- dbus_connection_unref (ptr);
- return c;
- } else {
- Exception e = new Exception (ref error);
- error.Free ();
- throw e;
- }
+ public void SetupWithMain()
+ {
+ dbus_connection_setup_with_g_main(RawConnection, IntPtr.Zero);
}
- public void Send (Message m,
- ref int serial) {
- if (!dbus_connection_send (raw, m.raw, ref serial))
- throw new OutOfMemoryException ();
- }
-
- public void Send (Message m) {
- int ignored = 0;
- Send (m, ref ignored);
- }
-
- public void Flush () {
- dbus_connection_flush (raw);
- }
-
- public void Disconnect () {
- dbus_connection_disconnect (raw);
+ ~Connection ()
+ {
+ if (RawConnection != IntPtr.Zero)
+ {
+ dbus_connection_disconnect(rawConnection);
+ }
+ RawConnection = IntPtr.Zero; // free the native object
}
- public static Connection Wrap (IntPtr ptr) {
- IntPtr gch_ptr;
-
- gch_ptr = dbus_connection_get_data (ptr, wrapper_slot);
- if (gch_ptr != IntPtr.Zero) {
- return (DBus.Connection) ((GCHandle)gch_ptr).Target;
- } else {
- return new Connection (ptr);
- }
- }
-
- // surely there's a convention for this pattern with the property
- // and the real member
- IntPtr raw_;
- internal IntPtr raw {
- get {
- return raw_;
- }
- set {
- if (value == raw_)
- return;
-
- if (raw_ != IntPtr.Zero) {
- IntPtr gch_ptr;
-
- gch_ptr = dbus_connection_get_data (raw_,
- wrapper_slot);
- Debug.Assert (gch_ptr != IntPtr.Zero);
-
- dbus_connection_set_data (raw_, wrapper_slot,
- IntPtr.Zero, IntPtr.Zero);
-
- ((GCHandle) gch_ptr).Free ();
-
- dbus_connection_unref (raw_);
- }
-
- raw_ = value;
-
- if (raw_ != IntPtr.Zero) {
- GCHandle gch;
-
- dbus_connection_ref (raw_);
-
- // We store a weak reference to the C# object on the C object
- gch = GCHandle.Alloc (this, GCHandleType.WeakTrackResurrection);
-
- dbus_connection_set_data (raw_, wrapper_slot,
- (IntPtr) gch, IntPtr.Zero);
- }
- }
+ internal static Connection Wrap(IntPtr rawConnection)
+ {
+ if (slot > -1) {
+ // If we already have a Connection object associated with this rawConnection then return it
+ IntPtr rawThis = dbus_connection_get_data (rawConnection, slot);
+ return (DBus.Connection) ((GCHandle)rawThis).Target;
+ }
+ else
+ {
+ // If it doesn't exist then create a new connection around it
+ return new Connection(rawConnection);
+ }
}
- ~Connection () {
- if (raw != IntPtr.Zero) {
- Disconnect ();
- }
- raw = IntPtr.Zero; // free the native object
+ public int Timeout
+ {
+ get
+ {
+ return this.timeout;
+ }
+ set
+ {
+ this.timeout = value;
+ }
}
- Connection (IntPtr r) {
- raw = r;
+ private int Slot
+ {
+ get
+ {
+ if (slot == -1)
+ {
+ // We need to initialize the slot
+ if (!dbus_connection_allocate_data_slot (ref slot))
+ throw new OutOfMemoryException ();
+
+ Debug.Assert (slot >= 0);
+ }
+
+ return slot;
+ }
}
- // static constructor runs before any methods
- static Connection () {
- DBus.Internals.Init ();
-
- Debug.Assert (wrapper_slot == -1);
-
- if (!dbus_connection_allocate_data_slot (ref wrapper_slot))
- throw new OutOfMemoryException ();
-
- Debug.Assert (wrapper_slot >= 0);
+ internal IntPtr RawConnection
+ {
+ get
+ {
+ return rawConnection;
+ }
+ set
+ {
+ if (value == rawConnection)
+ return;
+
+ if (rawConnection != IntPtr.Zero)
+ {
+ // Get the reference to this
+ IntPtr rawThis = dbus_connection_get_data (rawConnection, Slot);
+ Debug.Assert (rawThis != IntPtr.Zero);
+
+ // Blank over the reference
+ dbus_connection_set_data (rawConnection, Slot, IntPtr.Zero, IntPtr.Zero);
+
+ // Free the reference
+ ((GCHandle) rawThis).Free();
+
+ // Unref the connection
+ dbus_connection_unref(rawConnection);
+ }
+
+ this.rawConnection = value;
+
+ if (rawConnection != IntPtr.Zero)
+ {
+ GCHandle rawThis;
+
+ dbus_connection_ref (rawConnection);
+
+ // We store a weak reference to the C# object on the C object
+ rawThis = GCHandle.Alloc (this, GCHandleType.WeakTrackResurrection);
+
+ dbus_connection_set_data(rawConnection, Slot, (IntPtr) rawThis, IntPtr.Zero);
+ }
+ }
}
- // slot used to store the C# object on the C object
- static int wrapper_slot = -1;
+ [DllImport("dbus-glib-1")]
+ private extern static void dbus_connection_setup_with_g_main(IntPtr rawConnection,
+ IntPtr rawContext);
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_connection_open")]
- private extern static IntPtr dbus_connection_open (string address,
- ref Error error);
-
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_connection_unref")]
- private extern static void dbus_connection_unref (IntPtr ptr);
-
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_connection_ref")]
- private extern static void dbus_connection_ref (IntPtr ptr);
-
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_connection_allocate_data_slot")]
- private extern static bool dbus_connection_allocate_data_slot (ref int slot);
-
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_connection_free_data_slot")]
- private extern static void dbus_connection_free_data_slot (ref int slot);
-
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_connection_set_data")]
- private extern static bool dbus_connection_set_data (IntPtr ptr,
- int slot,
- IntPtr data,
- IntPtr free_data_func);
-
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_connection_send")]
- private extern static bool dbus_connection_send (IntPtr ptr,
- IntPtr message,
- ref int client_serial);
-
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_connection_flush")]
- private extern static void dbus_connection_flush (IntPtr ptr);
+ [DllImport ("dbus-1")]
+ private extern static IntPtr dbus_connection_open (string address, ref Error error);
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_bus_get")]
- private extern static IntPtr dbus_bus_get (int which,
- ref Error error);
+ [DllImport ("dbus-1")]
+ private extern static void dbus_connection_unref (IntPtr ptr);
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_connection_get_data")]
- private extern static IntPtr dbus_connection_get_data (IntPtr ptr,
- int slot);
-
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_connection_disconnect")]
- private extern static void dbus_connection_disconnect (IntPtr ptr);
+ [DllImport ("dbus-1")]
+ private extern static void dbus_connection_ref (IntPtr ptr);
+
+ [DllImport ("dbus-1")]
+ private extern static bool dbus_connection_allocate_data_slot (ref int slot);
+
+ [DllImport ("dbus-1")]
+ private extern static void dbus_connection_free_data_slot (ref int slot);
+
+ [DllImport ("dbus-1")]
+ private extern static bool dbus_connection_set_data (IntPtr ptr,
+ int slot,
+ IntPtr data,
+ IntPtr free_data_func);
+
+ [DllImport ("dbus-1")]
+ private extern static void dbus_connection_flush (IntPtr ptr);
- [DllImport (DBus.Internals.DBusGLibname, EntryPoint="dbus_connection_setup_with_g_main")]
- private extern static void dbus_connection_setup_with_g_main (IntPtr ptr,
- IntPtr context);
+ [DllImport ("dbus-1")]
+ private extern static IntPtr dbus_connection_get_data (IntPtr ptr,
+ int slot);
+ [DllImport ("dbus-1")]
+ private extern static void dbus_connection_disconnect (IntPtr ptr);
}
}
diff --git a/mono/Custom.cs b/mono/Custom.cs
new file mode 100644
index 00000000..f96562b9
--- /dev/null
+++ b/mono/Custom.cs
@@ -0,0 +1,18 @@
+using System;
+
+using DBus;
+
+namespace DBus
+{
+ public struct Custom
+ {
+ public string Name;
+ public byte[] Data;
+
+ public Custom(string name, byte[] data)
+ {
+ Name = name;
+ Data = data;
+ }
+ }
+}
diff --git a/mono/DBus.cs b/mono/DBus.cs
deleted file mode 100644
index 377af742..00000000
--- a/mono/DBus.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-namespace DBus {
-
- using System;
- using System.Runtime.InteropServices;
-
- public class Exception : ApplicationException {
- internal Exception (ref Error error)
- : base (Runtime.InteropServices.Marshal.PtrToStringAnsi (error.message)) { }
- }
-
- internal class Internals {
- internal const string DBusLibname = "libdbus-1.so.0";
- internal const string DBusGLibname = "libdbus-glib-1.so.0";
- internal const string GLibname = "libglib-2.0.so.0";
- internal const string GThreadname = "libgthread-2.0.so.0";
-
- internal static void Init () {
- dbus_gthread_init ();
- }
-
- [DllImport (DBus.Internals.DBusGLibname, EntryPoint="dbus_gthread_init")]
- private extern static void dbus_gthread_init ();
- }
-}
diff --git a/mono/DBusException.cs b/mono/DBusException.cs
new file mode 100644
index 00000000..5c912cca
--- /dev/null
+++ b/mono/DBusException.cs
@@ -0,0 +1,12 @@
+namespace DBus
+{
+ using System;
+ using System.Runtime.InteropServices;
+
+ public class DBusException : ApplicationException
+ {
+ internal DBusException (Error error) : base (error.Message) {
+ error.Free();
+ }
+ }
+}
diff --git a/mono/DBusType/Array.cs b/mono/DBusType/Array.cs
new file mode 100644
index 00000000..3bce3afa
--- /dev/null
+++ b/mono/DBusType/Array.cs
@@ -0,0 +1,130 @@
+using System;
+using System.Collections;
+using System.Runtime.InteropServices;
+using System.Reflection.Emit;
+
+using DBus;
+
+namespace DBus.DBusType
+{
+ /// <summary>
+ /// Array.
+ /// </summary>
+ public class Array : IDBusType
+ {
+ public const char Code = 'a';
+ private System.Array val;
+ private ArrayList elements;
+ private Type elementType;
+
+ private Array()
+ {
+ }
+
+ public Array(System.Array val)
+ {
+ this.val = val;
+ this.elementType = Arguments.MatchType(val.GetType().UnderlyingSystemType);
+ }
+
+ public Array(IntPtr iter)
+ {
+ IntPtr arrayIter = Marshal.AllocCoTaskMem(Arguments.DBusMessageIterSize);
+
+ int elementTypeCode;
+ dbus_message_iter_init_array_iterator(iter, arrayIter, out elementTypeCode);
+ this.elementType = (Type) Arguments.DBusTypes[(char) elementTypeCode];
+
+ elements = new ArrayList();
+
+ do {
+ object [] pars = new Object[1];
+ pars[0] = arrayIter;
+ DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars);
+ elements.Add(dbusType);
+ } while (dbus_message_iter_next(arrayIter));
+
+ Marshal.FreeCoTaskMem(arrayIter);
+ }
+
+ public void Append(IntPtr iter)
+ {
+ IntPtr arrayIter = Marshal.AllocCoTaskMem(Arguments.DBusMessageIterSize);
+
+ if (!dbus_message_iter_append_array(iter,
+ arrayIter,
+ (int) Arguments.GetCode(this.elementType))) {
+ throw new ApplicationException("Failed to append INT32 argument:" + val);
+ }
+
+ foreach (object element in this.val) {
+ object [] pars = new Object[1];
+ pars[0] = element;
+ DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars);
+ dbusType.Append(arrayIter);
+ }
+
+ Marshal.FreeCoTaskMem(arrayIter);
+ }
+
+ public static bool Suits(System.Type type)
+ {
+ if (type.IsArray) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public static void EmitMarshalIn(ILGenerator generator, Type type)
+ {
+ if (type.IsByRef) {
+ generator.Emit(OpCodes.Ldind_Ref);
+ }
+ }
+
+ public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn)
+ {
+ generator.Emit(OpCodes.Castclass, type);
+ if (!isReturn) {
+ generator.Emit(OpCodes.Stind_Ref);
+ }
+ }
+
+ public object Get()
+ {
+ throw new ArgumentException("Cannot call Get on an Array without specifying type.");
+ }
+
+ public object Get(System.Type type)
+ {
+ if (Arguments.Suits(elementType, type.UnderlyingSystemType)) {
+ this.val = System.Array.CreateInstance(type.UnderlyingSystemType, elements.Count);
+ int i = 0;
+ foreach (DBusType.IDBusType element in elements) {
+ this.val.SetValue(element.Get(type.UnderlyingSystemType), i++);
+ }
+ } else {
+ throw new ArgumentException("Cannot cast DBus.Type.Array to type '" + type.ToString() + "'");
+ }
+
+ return this.val;
+ }
+
+ [DllImport("dbus-1")]
+ private extern static void dbus_message_iter_init_array_iterator(IntPtr iter,
+ IntPtr arrayIter,
+ out int elementType);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_append_array(IntPtr iter,
+ IntPtr arrayIter,
+ int elementType);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_has_next(IntPtr iter);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_next(IntPtr iter);
+ }
+}
diff --git a/mono/DBusType/Boolean.cs b/mono/DBusType/Boolean.cs
new file mode 100644
index 00000000..ef8ed498
--- /dev/null
+++ b/mono/DBusType/Boolean.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Reflection.Emit;
+
+using DBus;
+
+namespace DBus.DBusType
+{
+ /// <summary>
+ /// Boolean
+ /// </summary>
+ public class Boolean : IDBusType
+ {
+ public const char Code = 'b';
+ private System.Boolean val;
+
+ private Boolean()
+ {
+ }
+
+ public Boolean(System.Boolean val)
+ {
+ this.val = val;
+ }
+
+ public Boolean(IntPtr iter)
+ {
+ this.val = dbus_message_iter_get_boolean(iter);
+ }
+
+ public void Append(IntPtr iter)
+ {
+ if (!dbus_message_iter_append_boolean(iter, val))
+ throw new ApplicationException("Failed to append BOOLEAN argument:" + val);
+ }
+
+ public static bool Suits(System.Type type)
+ {
+ switch (type.ToString()) {
+ case "System.Boolean":
+ case "System.Boolean&":
+ return true;
+ }
+
+ return false;
+ }
+
+ public static void EmitMarshalIn(ILGenerator generator, Type type)
+ {
+ if (type.IsByRef) {
+ generator.Emit(OpCodes.Ldind_I1);
+ }
+ }
+
+ public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn)
+ {
+ generator.Emit(OpCodes.Unbox, type);
+ generator.Emit(OpCodes.Ldind_I1);
+ if (!isReturn) {
+ generator.Emit(OpCodes.Stind_I1);
+ }
+ }
+
+ public object Get()
+ {
+ return this.val;
+ }
+
+ public object Get(System.Type type)
+ {
+ switch (type.ToString()) {
+ case "System.Boolean":
+ case "System.Boolean&":
+ return this.val;
+ default:
+ throw new ArgumentException("Cannot cast DBus.Type.Boolean to type '" + type.ToString() + "'");
+ }
+ }
+
+ [DllImport("dbus-1")]
+ private extern static System.Boolean dbus_message_iter_get_boolean(IntPtr iter);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_append_boolean(IntPtr iter, System.Boolean value);
+ }
+}
diff --git a/mono/DBusType/Byte.cs b/mono/DBusType/Byte.cs
new file mode 100644
index 00000000..eaffd26e
--- /dev/null
+++ b/mono/DBusType/Byte.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Reflection.Emit;
+
+using DBus;
+
+namespace DBus.DBusType
+{
+ /// <summary>
+ /// Byte
+ /// </summary>
+ public class Byte : IDBusType
+ {
+ public const char Code = 'y';
+ private System.Byte val;
+
+ private Byte()
+ {
+ }
+
+ public Byte(System.Byte val)
+ {
+ this.val = val;
+ }
+
+ public Byte(IntPtr iter)
+ {
+ this.val = dbus_message_iter_get_byte(iter);
+ }
+
+ public void Append(IntPtr iter)
+ {
+ if (!dbus_message_iter_append_byte(iter, val))
+ throw new ApplicationException("Failed to append BYTE argument:" + val);
+ }
+
+ public static bool Suits(System.Type type)
+ {
+ switch (type.ToString()) {
+ case "System.Byte":
+ case "System.Byte&":
+ return true;
+ }
+
+ return false;
+ }
+
+ public static void EmitMarshalIn(ILGenerator generator, Type type)
+ {
+ if (type.IsByRef) {
+ generator.Emit(OpCodes.Ldind_U1);
+ }
+ }
+
+ public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn)
+ {
+ generator.Emit(OpCodes.Unbox, type);
+ generator.Emit(OpCodes.Ldind_U1);
+ if (!isReturn) {
+ generator.Emit(OpCodes.Stind_I1);
+ }
+ }
+
+ public object Get()
+ {
+ return this.val;
+ }
+
+ public object Get(System.Type type)
+ {
+ switch (type.ToString()) {
+ case "System.Byte":
+ case "System.Byte&":
+ return this.val;
+ default:
+ throw new ArgumentException("Cannot cast DBus.Type.Byte to type '" + type.ToString() + "'");
+ }
+ }
+
+ [DllImport("dbus-1")]
+ private extern static System.Byte dbus_message_iter_get_byte(IntPtr iter);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_append_byte(IntPtr iter, System.Byte value);
+ }
+}
diff --git a/mono/DBusType/Custom.cs b/mono/DBusType/Custom.cs
new file mode 100644
index 00000000..d3eb7629
--- /dev/null
+++ b/mono/DBusType/Custom.cs
@@ -0,0 +1,109 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Reflection.Emit;
+
+using DBus;
+
+namespace DBus.DBusType
+{
+ /// <summary>
+ /// A named byte array, used for custom types.
+ /// </summary>
+ public class Custom : IDBusType
+ {
+ public const char Code = 'c';
+ private DBus.Custom val;
+
+ private Custom()
+ {
+ }
+
+ public Custom(DBus.Custom val)
+ {
+ this.val = val;
+ }
+
+ public Custom(IntPtr iter)
+ {
+ string name;
+ IntPtr value;
+ int len;
+
+ if (!dbus_message_iter_get_custom(iter, out name, out value, out len)) {
+ throw new ApplicationException("Failed to get CUSTOM argument.");
+ }
+
+ this.val.Name = name;
+ this.val.Data = new byte[len];
+ Marshal.Copy(value, this.val.Data, 0, len);
+ }
+
+ public void Append(IntPtr iter)
+ {
+ IntPtr data = Marshal.AllocCoTaskMem(this.val.Data.Length);
+ try {
+ Marshal.Copy(this.val.Data, 0, data, this.val.Data.Length);
+ if (!dbus_message_iter_append_custom(iter, this.val.Name, data, this.val.Data.Length)) {
+ throw new ApplicationException("Failed to append CUSTOM argument:" + val);
+ }
+ } finally {
+ Marshal.FreeCoTaskMem(data);
+ }
+ }
+
+ public static bool Suits(System.Type type)
+ {
+ switch (type.ToString()) {
+ case "DBus.Custom":
+ case "DBus.Custom&":
+ return true;
+ }
+
+ return false;
+ }
+
+ public static void EmitMarshalIn(ILGenerator generator, Type type)
+ {
+ if (type.IsByRef) {
+ generator.Emit(OpCodes.Ldobj, type);
+ }
+ }
+
+ public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn)
+ {
+ generator.Emit(OpCodes.Unbox, type);
+ generator.Emit(OpCodes.Ldobj, type);
+ if (!isReturn) {
+ generator.Emit(OpCodes.Stobj, type);
+ }
+ }
+
+ public object Get()
+ {
+ return this.val;
+ }
+
+ public object Get(System.Type type)
+ {
+ switch (type.ToString()) {
+ case "DBus.Custom":
+ case "DBus.Custom&":
+ return this.val;
+ default:
+ throw new ArgumentException("Cannot cast DBus.Type.Custom to type '" + type.ToString() + "'");
+ }
+ }
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_get_custom(IntPtr iter,
+ out string name,
+ out IntPtr value,
+ out int len);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_append_custom(IntPtr iter,
+ string name,
+ IntPtr data,
+ int len);
+ }
+}
diff --git a/mono/DBusType/Dict.cs b/mono/DBusType/Dict.cs
new file mode 100644
index 00000000..e6fce159
--- /dev/null
+++ b/mono/DBusType/Dict.cs
@@ -0,0 +1,145 @@
+using System;
+using System.Collections;
+using System.Runtime.InteropServices;
+using System.Reflection.Emit;
+
+using DBus;
+
+namespace DBus.DBusType
+{
+ /// <summary>
+ /// Dict.
+ /// </summary>
+ public class Dict : IDBusType
+ {
+ public const char Code = 'm';
+ private Hashtable val;
+
+ private Dict()
+ {
+ }
+
+ public Dict(IDictionary val)
+ {
+ this.val = new Hashtable();
+ foreach (DictionaryEntry entry in val) {
+ this.val.Add(entry.Key, entry.Value);
+ }
+ }
+
+ public Dict(IntPtr iter)
+ {
+ IntPtr dictIter = Marshal.AllocCoTaskMem(Arguments.DBusMessageIterSize);
+
+ dbus_message_iter_init_dict_iterator(iter, dictIter);
+
+ this.val = new Hashtable();
+
+ do {
+ string key = dbus_message_iter_get_dict_key(dictIter);
+
+ // Get the argument type and get the value
+ Type elementType = (Type) DBus.Arguments.DBusTypes[(char) dbus_message_iter_get_arg_type(dictIter)];
+ object [] pars = new Object[1];
+ pars[0] = dictIter;
+ DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars);
+ this.val.Add(key, dbusType);
+ } while (dbus_message_iter_next(dictIter));
+
+ Marshal.FreeCoTaskMem(dictIter);
+ }
+
+ public void Append(IntPtr iter)
+ {
+ IntPtr dictIter = Marshal.AllocCoTaskMem(Arguments.DBusMessageIterSize);
+
+ if (!dbus_message_iter_append_dict(iter,
+ dictIter)) {
+ throw new ApplicationException("Failed to append DICT argument:" + val);
+ }
+
+ foreach (DictionaryEntry entry in this.val) {
+ if (!dbus_message_iter_append_dict_key(dictIter, (string) entry.Key)) {
+ throw new ApplicationException("Failed to append DICT key:" + entry.Key);
+ }
+
+ // Get the element type
+ Type elementType = Arguments.MatchType(entry.Value.GetType());
+ object [] pars = new Object[1];
+ pars[0] = entry.Value;
+ DBusType.IDBusType dbusType = (DBusType.IDBusType) Activator.CreateInstance(elementType, pars);
+ dbusType.Append(dictIter);
+ }
+
+ Marshal.FreeCoTaskMem(dictIter);
+ }
+
+ public static bool Suits(System.Type type)
+ {
+ if (typeof(IDictionary).IsAssignableFrom(type)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public static void EmitMarshalIn(ILGenerator generator, Type type)
+ {
+ if (type.IsByRef) {
+ generator.Emit(OpCodes.Ldind_Ref);
+ }
+ }
+
+ public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn)
+ {
+ generator.Emit(OpCodes.Castclass, type);
+ if (!isReturn) {
+ generator.Emit(OpCodes.Stind_Ref);
+ }
+ }
+
+ public object Get()
+ {
+ return Get(typeof(Hashtable));
+ }
+
+ public object Get(System.Type type)
+ {
+ IDictionary retVal;
+
+ if (Suits(type)) {
+ retVal = (IDictionary) Activator.CreateInstance(type, new object[0]);
+ foreach (DictionaryEntry entry in this.val) {
+ retVal.Add(entry.Key, ((IDBusType) entry.Value).Get());
+ }
+ } else {
+ throw new ArgumentException("Cannot cast DBus.Type.Dict to type '" + type.ToString() + "'");
+ }
+
+ return retVal;
+ }
+
+ [DllImport("dbus-1")]
+ private extern static void dbus_message_iter_init_dict_iterator(IntPtr iter,
+ IntPtr dictIter);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_append_dict(IntPtr iter,
+ IntPtr dictIter);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_has_next(IntPtr iter);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_next(IntPtr iter);
+
+ [DllImport("dbus-1")]
+ private extern static string dbus_message_iter_get_dict_key (IntPtr dictIter);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_append_dict_key (IntPtr dictIter,
+ string value);
+ [DllImport("dbus-1")]
+ private extern static int dbus_message_iter_get_arg_type(IntPtr iter);
+ }
+}
diff --git a/mono/DBusType/Double.cs b/mono/DBusType/Double.cs
new file mode 100644
index 00000000..d578822f
--- /dev/null
+++ b/mono/DBusType/Double.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Reflection.Emit;
+
+using DBus;
+
+namespace DBus.DBusType
+{
+ /// <summary>
+ /// IEEE 754 double
+ /// </summary>
+ public class Double : IDBusType
+ {
+ public const char Code = 'd';
+ private System.Double val;
+
+ private Double()
+ {
+ }
+
+ public Double(System.Double val)
+ {
+ this.val = val;
+ }
+
+ public Double(IntPtr iter)
+ {
+ this.val = dbus_message_iter_get_double(iter);
+ }
+
+ public void Append(IntPtr iter)
+ {
+ if (!dbus_message_iter_append_double(iter, val))
+ throw new ApplicationException("Failed to append DOUBLE argument:" + val);
+ }
+
+ public static bool Suits(System.Type type)
+ {
+ switch (type.ToString()) {
+ case "System.Double":
+ case "System.Double&":
+ return true;
+ }
+
+ return false;
+ }
+
+ public static void EmitMarshalIn(ILGenerator generator, Type type)
+ {
+ if (type.IsByRef) {
+ generator.Emit(OpCodes.Ldind_R8);
+ }
+ }
+
+ public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn)
+ {
+ generator.Emit(OpCodes.Unbox, type);
+ generator.Emit(OpCodes.Ldind_R8);
+ if (!isReturn) {
+ generator.Emit(OpCodes.Stind_R8);
+ }
+ }
+
+ public object Get()
+ {
+ return this.val;
+ }
+
+ public object Get(System.Type type)
+ {
+ switch (type.ToString()) {
+ case "System.Double":
+ case "System.Double&":
+ return this.val;
+ default:
+ throw new ArgumentException("Cannot cast DBus.Type.Double to type '" + type.ToString() + "'");
+ }
+ }
+
+ [DllImport("dbus-1")]
+ private extern static System.Double dbus_message_iter_get_double(IntPtr iter);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_append_double(IntPtr iter, System.Double value);
+ }
+}
diff --git a/mono/DBusType/IDBusType.cs b/mono/DBusType/IDBusType.cs
new file mode 100644
index 00000000..447c8208
--- /dev/null
+++ b/mono/DBusType/IDBusType.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace DBus.DBusType
+{
+ /// <summary>
+ /// Base class for DBusTypes
+ /// </summary>
+ public interface IDBusType
+ {
+ object Get();
+
+ object Get(System.Type type);
+
+ void Append(IntPtr iter);
+ }
+}
diff --git a/mono/DBusType/Int32.cs b/mono/DBusType/Int32.cs
new file mode 100644
index 00000000..b617a9a0
--- /dev/null
+++ b/mono/DBusType/Int32.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Reflection.Emit;
+
+using DBus;
+
+namespace DBus.DBusType
+{
+ /// <summary>
+ /// 32-bit integer.
+ /// </summary>
+ public class Int32 : IDBusType
+ {
+ public const char Code = 'i';
+ private System.Int32 val;
+
+ private Int32()
+ {
+ }
+
+ public Int32(System.Int32 val)
+ {
+ this.val = val;
+ }
+
+ public Int32(IntPtr iter)
+ {
+ this.val = dbus_message_iter_get_int32(iter);
+ }
+
+ public void Append(IntPtr iter)
+ {
+ if (!dbus_message_iter_append_int32(iter, val))
+ throw new ApplicationException("Failed to append INT32 argument:" + val);
+ }
+
+ public static bool Suits(System.Type type)
+ {
+ switch (type.ToString()) {
+ case "System.Int32":
+ case "System.Int32&":
+ return true;
+ }
+
+ return false;
+ }
+
+ public static void EmitMarshalIn(ILGenerator generator, Type type)
+ {
+ if (type.IsByRef) {
+ generator.Emit(OpCodes.Ldind_I4);
+ }
+ }
+
+ public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn)
+ {
+ generator.Emit(OpCodes.Unbox, type);
+ generator.Emit(OpCodes.Ldind_I4);
+ if (!isReturn) {
+ generator.Emit(OpCodes.Stind_I4);
+ }
+ }
+
+ public object Get()
+ {
+ return this.val;
+ }
+
+ public object Get(System.Type type)
+ {
+ switch (type.ToString()) {
+ case "System.Int32":
+ case "System.Int32&":
+ return this.val;
+ default:
+ throw new ArgumentException("Cannot cast DBus.Type.Int32 to type '" + type.ToString() + "'");
+ }
+ }
+
+ [DllImport("dbus-1")]
+ private extern static System.Int32 dbus_message_iter_get_int32(IntPtr iter);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_append_int32(IntPtr iter, System.Int32 value);
+ }
+}
diff --git a/mono/DBusType/Int64.cs b/mono/DBusType/Int64.cs
new file mode 100644
index 00000000..0905af74
--- /dev/null
+++ b/mono/DBusType/Int64.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Reflection.Emit;
+
+using DBus;
+
+namespace DBus.DBusType
+{
+ /// <summary>
+ /// 64-bit integer.
+ /// </summary>
+ public class Int64 : IDBusType
+ {
+ public const char Code = 'x';
+ private System.Int64 val;
+
+ private Int64()
+ {
+ }
+
+ public Int64(System.Int64 val)
+ {
+ this.val = val;
+ }
+
+ public Int64(IntPtr iter)
+ {
+ this.val = dbus_message_iter_get_int64(iter);
+ }
+
+ public void Append(IntPtr iter)
+ {
+ if (!dbus_message_iter_append_int64(iter, val))
+ throw new ApplicationException("Failed to append INT64 argument:" + val);
+ }
+
+ public static bool Suits(System.Type type)
+ {
+ switch (type.ToString()) {
+ case "System.Int64":
+ case "System.Int64&":
+ return true;
+ }
+
+ return false;
+ }
+
+ public static void EmitMarshalIn(ILGenerator generator, Type type)
+ {
+ if (type.IsByRef) {
+ generator.Emit(OpCodes.Ldind_I8);
+ }
+ }
+
+ public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn)
+ {
+ generator.Emit(OpCodes.Unbox, type);
+ generator.Emit(OpCodes.Ldind_I8);
+ if (!isReturn) {
+ generator.Emit(OpCodes.Stind_I8);
+ }
+ }
+
+ public object Get()
+ {
+ return this.val;
+ }
+
+ public object Get(System.Type type)
+ {
+ switch (type.ToString()) {
+ case "System.Int64":
+ case "System.Int64&":
+ return this.val;
+ default:
+ throw new ArgumentException("Cannot cast DBus.Type.Int64 to type '" + type.ToString() + "'");
+ }
+ }
+
+ [DllImport("dbus-1")]
+ private extern static System.Int64 dbus_message_iter_get_int64(IntPtr iter);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_append_int64(IntPtr iter, System.Int64 value);
+ }
+}
diff --git a/mono/DBusType/Nil.cs b/mono/DBusType/Nil.cs
new file mode 100644
index 00000000..e39b64a9
--- /dev/null
+++ b/mono/DBusType/Nil.cs
@@ -0,0 +1,68 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Reflection.Emit;
+
+using DBus;
+
+namespace DBus.DBusType
+{
+ /// <summary>
+ /// Marks a "void"/"unset"/"nonexistent"/"null" argument.
+ /// </summary>
+ public class Nil : IDBusType
+ {
+ public const char Code = 'v';
+
+ private Nil()
+ {
+ }
+
+ public Nil(object nil)
+ {
+ }
+
+ public Nil(IntPtr iter)
+ {
+ }
+
+ public void Append(IntPtr iter)
+ {
+ if (!dbus_message_iter_append_nil(iter))
+ throw new ApplicationException("Failed to append NIL argument");
+ }
+
+ public static bool Suits(System.Type type)
+ {
+ return false;
+ }
+
+ public static void EmitMarshalIn(ILGenerator generator, Type type)
+ {
+ if (type.IsByRef) {
+ generator.Emit(OpCodes.Ldind_I1);
+ }
+ }
+
+ public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn)
+ {
+ generator.Emit(OpCodes.Unbox, type);
+ generator.Emit(OpCodes.Ldind_I1);
+ if (!isReturn) {
+ generator.Emit(OpCodes.Stind_I1);
+ }
+ }
+
+ public object Get()
+ {
+ return null;
+ }
+
+ public object Get(System.Type type)
+ {
+ throw new ArgumentException("Cannot cast DBus.Type.Nil to type '" + type.ToString() + "'");
+ }
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_append_nil(IntPtr iter);
+ }
+}
diff --git a/mono/DBusType/ObjectPath.cs b/mono/DBusType/ObjectPath.cs
new file mode 100644
index 00000000..e20ae18d
--- /dev/null
+++ b/mono/DBusType/ObjectPath.cs
@@ -0,0 +1,110 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Reflection.Emit;
+
+using DBus;
+
+namespace DBus.DBusType
+{
+ /// <summary>
+ /// An object path.
+ /// </summary>
+ public class ObjectPath : IDBusType
+ {
+ public const char Code = 'o';
+ private string pathName = null;
+ private object val = null;
+ private Service service = null;
+
+ private ObjectPath()
+ {
+ }
+
+ public ObjectPath(object val)
+ {
+ this.val = val;
+ }
+
+ public ObjectPath(IntPtr iter)
+ {
+
+ this.pathName = Marshal.PtrToStringAnsi(dbus_message_iter_get_object_path(iter));
+ }
+
+ public void SetService(Service service)
+ {
+ this.service = service;
+ }
+
+ private string PathName
+ {
+ get {
+ if (this.pathName == null && this.val != null) {
+ Handler handler = this.service.GetHandler(this.val);
+ this.pathName = handler.PathName;
+ }
+
+ return this.pathName;
+ }
+ }
+
+ public void Append(IntPtr iter)
+ {
+ if (PathName == null) {
+ throw new ApplicationException("Unable to append ObjectPath before calling SetService()");
+ }
+
+ if (!dbus_message_iter_append_object_path(iter, Marshal.StringToHGlobalAnsi(PathName)))
+ throw new ApplicationException("Failed to append OBJECT_PATH argument:" + val);
+ }
+
+ public static bool Suits(System.Type type)
+ {
+ object[] attributes = type.GetCustomAttributes(typeof(InterfaceAttribute), true);
+ if (attributes.Length == 1) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public static void EmitMarshalIn(ILGenerator generator, Type type)
+ {
+ if (type.IsByRef) {
+ generator.Emit(OpCodes.Ldind_Ref);
+ }
+ }
+
+ public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn)
+ {
+ generator.Emit(OpCodes.Castclass, type);
+ if (!isReturn) {
+ generator.Emit(OpCodes.Stind_Ref);
+ }
+ }
+
+ public object Get()
+ {
+ throw new ArgumentException("Cannot call Get on an ObjectPath without specifying type.");
+ }
+
+ public object Get(System.Type type)
+ {
+ if (this.service == null) {
+ throw new ApplicationException("Unable to get ObjectPath before calling SetService()");
+ }
+
+ try {
+ return this.service.GetObject(type, PathName);
+ } catch(Exception ex) {
+ throw new ArgumentException("Cannot cast object pointed to by Object Path to type '" + type.ToString() + "': " + ex);
+ }
+ }
+
+ [DllImport("dbus-1")]
+ private extern static IntPtr dbus_message_iter_get_object_path(IntPtr iter);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_append_object_path(IntPtr iter, IntPtr pathName);
+ }
+}
diff --git a/mono/DBusType/String.cs b/mono/DBusType/String.cs
new file mode 100644
index 00000000..1eda1f25
--- /dev/null
+++ b/mono/DBusType/String.cs
@@ -0,0 +1,86 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Reflection.Emit;
+
+using DBus;
+
+namespace DBus.DBusType
+{
+ /// <summary>
+ /// A string.
+ /// </summary>
+ public class String : IDBusType
+ {
+ public const char Code = 's';
+ private string val;
+
+ private String()
+ {
+ }
+
+ public String(string val)
+ {
+ this.val = val;
+ }
+
+ public String(IntPtr iter)
+ {
+ this.val = Marshal.PtrToStringAnsi(dbus_message_iter_get_string(iter));
+ }
+
+ public void Append(IntPtr iter)
+ {
+ if (!dbus_message_iter_append_string(iter, Marshal.StringToHGlobalAnsi(val)))
+ throw new ApplicationException("Failed to append STRING argument:" + val);
+ }
+
+ public static bool Suits(System.Type type)
+ {
+ switch (type.ToString()) {
+ case "System.String":
+ case "System.String&":
+ return true;
+ }
+
+ return false;
+ }
+
+ public static void EmitMarshalIn(ILGenerator generator, Type type)
+ {
+ if (type.IsByRef) {
+ generator.Emit(OpCodes.Ldind_Ref);
+ }
+ }
+
+ public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn)
+ {
+ generator.Emit(OpCodes.Castclass, type);
+ if (!isReturn) {
+ generator.Emit(OpCodes.Stind_Ref);
+ }
+ }
+
+ public object Get()
+ {
+ return this.val;
+ }
+
+ public object Get(System.Type type)
+ {
+ switch (type.ToString())
+ {
+ case "System.String":
+ case "System.String&":
+ return this.val;
+ default:
+ throw new ArgumentException("Cannot cast DBus.Type.String to type '" + type.ToString() + "'");
+ }
+ }
+
+ [DllImport("dbus-1")]
+ private extern static IntPtr dbus_message_iter_get_string(IntPtr iter);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_append_string(IntPtr iter, IntPtr value);
+ }
+}
diff --git a/mono/DBusType/UInt32.cs b/mono/DBusType/UInt32.cs
new file mode 100644
index 00000000..9c0e350a
--- /dev/null
+++ b/mono/DBusType/UInt32.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Reflection.Emit;
+
+using DBus;
+
+namespace DBus.DBusType
+{
+ /// <summary>
+ /// 32-bit unsigned integer.
+ /// </summary>
+ public class UInt32 : IDBusType
+ {
+ public const char Code = 'u';
+ private System.UInt32 val;
+
+ private UInt32()
+ {
+ }
+
+ public UInt32(System.UInt32 val)
+ {
+ this.val = val;
+ }
+
+ public UInt32(IntPtr iter)
+ {
+ this.val = dbus_message_iter_get_uint32(iter);
+ }
+
+ public void Append(IntPtr iter)
+ {
+ if (!dbus_message_iter_append_uint32(iter, val))
+ throw new ApplicationException("Failed to append UINT32 argument:" + val);
+ }
+
+ public static bool Suits(System.Type type)
+ {
+ switch (type.ToString()) {
+ case "System.UInt32":
+ case "System.UInt32&":
+ return true;
+ }
+
+ return false;
+ }
+
+ public static void EmitMarshalIn(ILGenerator generator, Type type)
+ {
+ if (type.IsByRef) {
+ generator.Emit(OpCodes.Ldind_U4);
+ }
+ }
+
+ public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn)
+ {
+ generator.Emit(OpCodes.Unbox, type);
+ generator.Emit(OpCodes.Ldind_U4);
+ if (!isReturn) {
+ generator.Emit(OpCodes.Stind_I4);
+ }
+ }
+
+ public object Get()
+ {
+ return this.val;
+ }
+
+ public object Get(System.Type type)
+ {
+ switch (type.ToString())
+ {
+ case "System.UInt32":
+ case "System.UInt32&":
+ return this.val;
+ default:
+ throw new ArgumentException("Cannot cast DBus.Type.UInt32 to type '" + type.ToString() + "'");
+ }
+ }
+
+ [DllImport("dbus-1")]
+ private extern static System.UInt32 dbus_message_iter_get_uint32(IntPtr iter);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_append_uint32(IntPtr iter, System.UInt32 value);
+ }
+}
diff --git a/mono/DBusType/UInt64.cs b/mono/DBusType/UInt64.cs
new file mode 100644
index 00000000..2e474795
--- /dev/null
+++ b/mono/DBusType/UInt64.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Reflection.Emit;
+
+using DBus;
+
+namespace DBus.DBusType
+{
+ /// <summary>
+ /// 64-bit unsigned integer.
+ /// </summary>
+ public class UInt64 : IDBusType
+ {
+ public const char Code = 't';
+ private System.UInt64 val;
+
+ private UInt64()
+ {
+ }
+
+ public UInt64(System.UInt64 val)
+ {
+ this.val = val;
+ }
+
+ public UInt64(IntPtr iter)
+ {
+ this.val = dbus_message_iter_get_uint64(iter);
+ }
+
+ public void Append(IntPtr iter)
+ {
+ if (!dbus_message_iter_append_uint64(iter, val))
+ throw new ApplicationException("Failed to append UINT64 argument:" + val);
+ }
+
+ public static bool Suits(System.Type type)
+ {
+ switch (type.ToString()) {
+ case "System.UInt64":
+ case "System.UInt64&":
+ return true;
+ }
+
+ return false;
+ }
+
+ public static void EmitMarshalIn(ILGenerator generator, Type type)
+ {
+ if (type.IsByRef) {
+ generator.Emit(OpCodes.Ldind_I8);
+ }
+ }
+
+ public static void EmitMarshalOut(ILGenerator generator, Type type, bool isReturn)
+ {
+ generator.Emit(OpCodes.Unbox, type);
+ generator.Emit(OpCodes.Ldind_I8);
+ if (!isReturn) {
+ generator.Emit(OpCodes.Stind_I8);
+ }
+ }
+
+ public object Get()
+ {
+ return this.val;
+ }
+
+ public object Get(System.Type type)
+ {
+ switch (type.ToString())
+ {
+ case "System.UInt64":
+ case "System.UInt64&":
+ return this.val;
+ default:
+ throw new ArgumentException("Cannot cast DBus.Type.UInt64 to type '" + type.ToString() + "'");
+ }
+ }
+
+ [DllImport("dbus-1")]
+ private extern static System.UInt64 dbus_message_iter_get_uint64(IntPtr iter);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_iter_append_uint64(IntPtr iter, System.UInt64 value);
+ }
+}
diff --git a/mono/Error.cs b/mono/Error.cs
index dab4df1f..d89a013a 100644
--- a/mono/Error.cs
+++ b/mono/Error.cs
@@ -1,29 +1,60 @@
-namespace DBus {
-
+namespace DBus
+{
+
using System;
using System.Runtime.InteropServices;
+ using System.Diagnostics;
// FIXME add code to verify that size of DBus.Error
// matches the C code.
-
+
[StructLayout (LayoutKind.Sequential)]
- internal struct Error {
+ internal struct Error
+ {
internal IntPtr name;
internal IntPtr message;
private int dummies;
private IntPtr padding1;
-
- internal void Init () {
- dbus_error_init (ref this);
+
+ public void Init()
+ {
+ dbus_error_init(ref this);
+ }
+
+ public void Free()
+ {
+ dbus_error_free(ref this);
}
- internal void Free () {
- dbus_error_free (ref this);
+ public string Message
+ {
+ get
+ {
+ return System.Runtime.InteropServices.Marshal.PtrToStringAnsi(message);
+ }
}
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_error_init")]
+ public string Name
+ {
+ get
+ {
+ return System.Runtime.InteropServices.Marshal.PtrToStringAnsi(name);
+ }
+ }
+
+ public bool IsSet
+ {
+ get
+ {
+ return (name != IntPtr.Zero);
+ }
+ }
+
+
+ [DllImport ("dbus-1", EntryPoint="dbus_error_init")]
private extern static void dbus_error_init (ref Error error);
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_error_free")]
+
+ [DllImport ("dbus-1", EntryPoint="dbus_error_free")]
private extern static void dbus_error_free (ref Error error);
}
}
diff --git a/mono/Handler.cs b/mono/Handler.cs
new file mode 100644
index 00000000..d565b7ec
--- /dev/null
+++ b/mono/Handler.cs
@@ -0,0 +1,256 @@
+namespace DBus
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics;
+ using System.Reflection;
+ using System.Collections;
+
+ internal class Handler
+ {
+ private string[] path = null;
+ private string pathName = null;
+ private Introspector introspector = null;
+ private object handledObject = null;
+ private Hashtable handledMethods = null;
+ private DBusObjectPathVTable vTable;
+ private Connection connection;
+ private Service service;
+ private DBusHandleMessageFunction filterCalled;
+
+ internal delegate void DBusObjectPathUnregisterFunction(IntPtr rawConnection,
+ IntPtr userData);
+
+ internal delegate int DBusObjectPathMessageFunction(IntPtr rawConnection,
+ IntPtr rawMessage,
+ IntPtr userData);
+
+ internal delegate int DBusHandleMessageFunction(IntPtr rawConnection,
+ IntPtr rawMessage,
+ IntPtr userData);
+
+
+ private enum Result
+ {
+ Handled = 0,
+ NotYetHandled = 1,
+ NeedMemory = 2
+ }
+
+ [StructLayout (LayoutKind.Sequential)]
+ private struct DBusObjectPathVTable
+ {
+ public DBusObjectPathUnregisterFunction unregisterFunction;
+ public DBusObjectPathMessageFunction messageFunction;
+ public IntPtr padding1;
+ public IntPtr padding2;
+ public IntPtr padding3;
+ public IntPtr padding4;
+
+ public DBusObjectPathVTable(DBusObjectPathUnregisterFunction unregisterFunction,
+ DBusObjectPathMessageFunction messageFunction)
+ {
+ this.unregisterFunction = unregisterFunction;
+ this.messageFunction = messageFunction;
+ this.padding1 = IntPtr.Zero;
+ this.padding2 = IntPtr.Zero;
+ this.padding3 = IntPtr.Zero;
+ this.padding4 = IntPtr.Zero;
+ }
+ }
+
+ ~Handler()
+ {
+ if (Connection != null && Connection.RawConnection != IntPtr.Zero && path != null) {
+ dbus_connection_unregister_object_path(Connection.RawConnection,
+ Path);
+ }
+ }
+
+ public Handler(object handledObject,
+ string pathName,
+ Service service)
+ {
+ Service = service;
+ Connection = service.Connection;
+ HandledObject = handledObject;
+
+ // Strip the leading / off if there is one and get the path as an array
+ pathName = pathName.TrimStart('/');
+ this.path = pathName.Split('/');
+ this.pathName = "/" + pathName;
+
+ // Create the vTable and register the path
+ vTable = new DBusObjectPathVTable(new DBusObjectPathUnregisterFunction(Unregister_Called),
+ new DBusObjectPathMessageFunction(Message_Called));
+
+ if (!dbus_connection_register_object_path(Connection.RawConnection,
+ Path,
+ ref vTable,
+ IntPtr.Zero))
+ throw new OutOfMemoryException();
+
+ // Setup the filter function
+ this.filterCalled = new DBusHandleMessageFunction(Filter_Called);
+ if (!dbus_connection_add_filter(Connection.RawConnection,
+ this.filterCalled,
+ IntPtr.Zero,
+ IntPtr.Zero))
+ throw new OutOfMemoryException();
+ }
+
+ private void RegisterMethod(MethodInfo method)
+ {
+ string key = method.Name + " " + Arguments.ParseParameters(method);
+ handledMethods.Add(key, method);
+ }
+
+ public object HandledObject
+ {
+ get
+ {
+ return this.handledObject;
+ }
+
+ set
+ {
+ this.handledObject = value;
+
+ object[] attributes;
+
+ // Register the methods
+ this.handledMethods = new Hashtable();
+ this.introspector = new Introspector(value.GetType());
+
+ foreach (MethodInfo method in this.introspector.Methods) {
+ RegisterMethod(method);
+ }
+ }
+ }
+
+ public int Filter_Called(IntPtr rawConnection,
+ IntPtr rawMessage,
+ IntPtr userData)
+ {
+ Message message = Message.Wrap(rawMessage, Service);
+
+ if (message.Type == Message.MessageType.Signal) {
+ Signal signal = (Signal) message;
+ } else if (message.Type == Message.MessageType.MethodCall) {
+ MethodCall methodCall = (MethodCall) message;
+ }
+
+ return (int) Result.NotYetHandled;
+ }
+
+ public void Unregister_Called(IntPtr rawConnection,
+ IntPtr userData)
+ {
+ System.Console.WriteLine("FIXME: Unregister called.");
+ }
+
+ private int Message_Called(IntPtr rawConnection,
+ IntPtr rawMessage,
+ IntPtr userData)
+ {
+ Message message = Message.Wrap(rawMessage, Service);
+
+ switch (message.Type) {
+ case Message.MessageType.Signal:
+ System.Console.WriteLine("FIXME: Signal called.");
+ break;
+ case Message.MessageType.MethodCall:
+ return (int) HandleMethod((MethodCall) message);
+ }
+
+ return (int) Result.NotYetHandled;
+ }
+
+ private Result HandleMethod(MethodCall methodCall)
+ {
+ methodCall.Service = service;
+
+ // Check the interface name matches
+ if (methodCall.InterfaceName != this.introspector.InterfaceName) {
+ return Result.NotYetHandled;
+ }
+
+ // Iterate through getting the type codes
+ string key = methodCall.Name + " " + methodCall.Arguments;
+
+ // Check it's one of our methods
+ if (!handledMethods.Contains(key)) {
+ return Result.NotYetHandled;
+ }
+
+ // Got it!
+ MethodInfo method = (MethodInfo) handledMethods[key];
+
+ // Now call the method. FIXME: Error handling
+ object [] args = methodCall.Arguments.GetParameters(method);
+ object retVal = method.Invoke(this.handledObject, args);
+
+ // Create the reply and send it
+ MethodReturn methodReturn = new MethodReturn(methodCall);
+ methodReturn.Arguments.AppendResults(method, retVal, args);
+ methodReturn.Send();
+
+ return Result.Handled;
+ }
+
+ internal string[] Path
+ {
+ get
+ {
+ return path;
+ }
+ }
+
+ public string PathName
+ {
+ get
+ {
+ return pathName;
+ }
+ }
+
+ internal Connection Connection
+ {
+ get
+ {
+ return connection;
+ }
+
+ set
+ {
+ this.connection = value;
+ }
+ }
+
+ public Service Service
+ {
+ get
+ {
+ return service;
+ }
+
+ set
+ {
+ this.service = value;
+ }
+ }
+
+ [DllImport ("dbus-1")]
+ private extern static bool dbus_connection_register_object_path (IntPtr rawConnection, string[] path, ref DBusObjectPathVTable vTable, IntPtr userData);
+
+ [DllImport ("dbus-1")]
+ private extern static void dbus_connection_unregister_object_path (IntPtr rawConnection, string[] path);
+
+ [DllImport ("dbus-1")]
+ private extern static bool dbus_connection_add_filter(IntPtr rawConnection,
+ DBusHandleMessageFunction filter,
+ IntPtr userData,
+ IntPtr freeData);
+
+ }
+}
diff --git a/mono/InterfaceAttribute.cs b/mono/InterfaceAttribute.cs
new file mode 100644
index 00000000..2a6e9bb0
--- /dev/null
+++ b/mono/InterfaceAttribute.cs
@@ -0,0 +1,23 @@
+using System;
+
+namespace DBus
+{
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple=false, Inherited=true)]
+ public class InterfaceAttribute : Attribute
+ {
+ private string interfaceName;
+
+ public InterfaceAttribute(string interfaceName)
+ {
+ this.interfaceName = interfaceName;
+ }
+
+ public string InterfaceName
+ {
+ get
+ {
+ return this.interfaceName;
+ }
+ }
+ }
+}
diff --git a/mono/Introspector.cs b/mono/Introspector.cs
new file mode 100644
index 00000000..c7b9d05b
--- /dev/null
+++ b/mono/Introspector.cs
@@ -0,0 +1,106 @@
+namespace DBus
+{
+
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics;
+ using System.Collections;
+ using System.Reflection;
+
+ internal class Introspector
+ {
+ private Type type;
+ private string interfaceName;
+
+ public Introspector(Type type) {
+ object[] attributes = type.GetCustomAttributes(typeof(InterfaceAttribute), true);
+ if (attributes.Length != 1)
+ throw new ApplicationException("Type '" + type + "' is not a D-BUS interface.");
+
+ InterfaceAttribute interfaceAttribute = (InterfaceAttribute) attributes[0];
+
+ this.interfaceName = interfaceAttribute.InterfaceName;
+ this.type = type;
+ }
+
+ public string InterfaceName
+ {
+ get
+ {
+ return this.interfaceName;
+ }
+ }
+
+ public ConstructorInfo Constructor
+ {
+ get
+ {
+ ConstructorInfo ret = this.type.GetConstructor(new Type[0]);
+ if (ret != null) {
+ return ret;
+ } else {
+ return typeof(object).GetConstructor(new Type[0]);
+ }
+ }
+ }
+
+ public IntrospectorMethods Methods
+ {
+ get
+ {
+ return new IntrospectorMethods(this.type);
+ }
+ }
+
+ public class IntrospectorMethods : IEnumerable
+ {
+ private Type type;
+
+ public IntrospectorMethods(Type type)
+ {
+ this.type = type;
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ return new MethodEnumerator(this.type.GetMethods(BindingFlags.Public|BindingFlags.Instance).GetEnumerator());
+ }
+
+ private class MethodEnumerator : IEnumerator
+ {
+ private IEnumerator enumerator;
+
+ public MethodEnumerator(IEnumerator enumerator)
+ {
+ this.enumerator = enumerator;
+ }
+
+ public bool MoveNext()
+ {
+ while (enumerator.MoveNext()) {
+ MethodInfo method = (MethodInfo) enumerator.Current;
+ object[] attributes = method.GetCustomAttributes(typeof(MethodAttribute), true);
+ if (attributes.GetLength(0) > 0) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public void Reset()
+ {
+ enumerator.Reset();
+ }
+
+ public object Current
+ {
+ get
+ {
+ return enumerator.Current;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/mono/Makefile.am b/mono/Makefile.am
index efd61b4b..6483f4ed 100644
--- a/mono/Makefile.am
+++ b/mono/Makefile.am
@@ -1,9 +1,41 @@
DESTDIR=
DLLS=dbus-sharp.dll
-NOINST_EXES=test-dbus-sharp
+NOINST_EXES=test-dbus-sharp.exe
+
+DBUS_SHARP_FILES= \
+ Arguments.cs \
+ Bus.cs \
+ Connection.cs \
+ Custom.cs \
+ DBusException.cs \
+ Error.cs \
+ Handler.cs \
+ InterfaceAttribute.cs \
+ Introspector.cs \
+ Message.cs \
+ MethodAttribute.cs \
+ MethodCall.cs \
+ MethodReturn.cs \
+ ProxyBuilder.cs \
+ Server.cs \
+ Service.cs \
+ Signal.cs \
+ DBusType/IDBusType.cs \
+ DBusType/Array.cs \
+ DBusType/Boolean.cs \
+ DBusType/Byte.cs \
+ DBusType/Custom.cs \
+ DBusType/Dict.cs \
+ DBusType/Double.cs \
+ DBusType/Int32.cs \
+ DBusType/Int64.cs \
+ DBusType/Nil.cs \
+ DBusType/ObjectPath.cs \
+ DBusType/String.cs \
+ DBusType/UInt32.cs \
+ DBusType/UInt64.cs
-DBUS_SHARP_FILES= DBus.cs Message.cs Connection.cs Error.cs
TEST_DBUS_SHARP_FILES=Test.cs
all: $(DLLS) $(NOINST_EXES)
@@ -11,8 +43,8 @@ all: $(DLLS) $(NOINST_EXES)
dbus-sharp.dll: $(DBUS_SHARP_FILES)
$(MCS) $(MCSFLAGS) --unsafe --target library -o dbus-sharp.dll $(DBUS_SHARP_FILES)
-test-dbus-sharp: $(TEST_DBUS_SHARP_FILES)
- $(MCS) $(MCSFLAGS) --unsafe --target exe -L . -r dbus-sharp.dll -o test-dbus-sharp $(TEST_DBUS_SHARP_FILES)
+test-dbus-sharp.exe: $(TEST_DBUS_SHARP_FILES)
+ $(MCS) $(MCSFLAGS) --unsafe --target exe -L . -r dbus-sharp.dll -r gtk-sharp.dll -o test-dbus-sharp.exe $(TEST_DBUS_SHARP_FILES)
clean:
rm -f $(DLLS) $(NOINST_EXES)
diff --git a/mono/Message.cs b/mono/Message.cs
index 8f6db007..2f5270dd 100644
--- a/mono/Message.cs
+++ b/mono/Message.cs
@@ -1,129 +1,358 @@
-namespace DBus {
+namespace DBus
+{
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
+ using System.Collections;
- public class Message {
+ public class Message
+ {
+
+ /// <summary>
+ /// A pointer to the underlying Message structure
+ /// </summary>
+ private IntPtr rawMessage;
+
+ /// <summary>
+ /// The current slot number
+ /// </summary>
+ private static int slot = -1;
+
+ // Keep in sync with C
+ public enum MessageType
+ {
+ Invalid = 0,
+ MethodCall = 1,
+ MethodReturn = 2,
+ Error = 3,
+ Signal = 4
+ }
- public Message (string name,
- string dest_service) {
+ private Arguments arguments = null;
+
+ protected Service service = null;
+ protected string pathName = null;
+ protected string interfaceName = null;
+ protected string name = null;
+
+ protected Message()
+ {
+ // An empty constructor for the sake of sub-classes which know how to construct theirselves.
+ }
+
+ protected Message(IntPtr rawMessage, Service service)
+ {
+ RawMessage = rawMessage;
+ this.service = service;
+ }
+
+ protected Message(MessageType messageType)
+ {
// the assignment bumps the refcount
- raw = dbus_message_new (name, dest_service);
- if (raw == IntPtr.Zero)
- throw new OutOfMemoryException ();
- dbus_message_unref (raw);
+ RawMessage = dbus_message_new((int) messageType);
+
+ if (RawMessage == IntPtr.Zero) {
+ throw new OutOfMemoryException();
+ }
+
+ dbus_message_unref(RawMessage);
}
-
- public string Name {
- get {
- return dbus_message_get_name (raw);
+
+ protected Message(MessageType messageType, Service service) : this(messageType)
+ {
+ this.service = service;
+ }
+
+ ~Message()
+ {
+ RawMessage = IntPtr.Zero; // free the native object
+ }
+
+ public static Message Wrap(IntPtr rawMessage, Service service)
+ {
+ if (slot > -1) {
+ // If we already have a Message object associated with this rawMessage then return it
+ IntPtr rawThis = dbus_message_get_data(rawMessage, slot);
+ if (rawThis != IntPtr.Zero)
+ return (DBus.Message) ((GCHandle)rawThis).Target;
+ }
+ // If it doesn't exist then create a new Message around it
+ Message message = null;
+
+ switch ((MessageType) dbus_message_get_type(rawMessage)) {
+ case MessageType.Signal:
+ message = new Signal(rawMessage, service);
+ break;
+ case MessageType.MethodCall:
+ message = new MethodCall(rawMessage, service);
+ break;
}
+
+ return message;
+ }
+
+ internal IntPtr RawMessage
+ {
+ get
+ {
+ return rawMessage;
+ }
+ set
+ {
+ if (value == rawMessage)
+ return;
+
+ if (rawMessage != IntPtr.Zero)
+ {
+ // Get the reference to this
+ IntPtr rawThis = dbus_message_get_data(rawMessage, Slot);
+ Debug.Assert (rawThis != IntPtr.Zero);
+
+ // Blank over the reference
+ dbus_message_set_data(rawMessage, Slot, IntPtr.Zero, IntPtr.Zero);
+
+ // Free the reference
+ ((GCHandle) rawThis).Free();
+
+ // Unref the connection
+ dbus_message_unref(rawMessage);
+ }
+
+ this.rawMessage = value;
+
+ if (rawMessage != IntPtr.Zero)
+ {
+ GCHandle rawThis;
+
+ dbus_message_ref(rawMessage);
+
+ // We store a weak reference to the C# object on the C object
+ rawThis = GCHandle.Alloc(this, GCHandleType.WeakTrackResurrection);
+
+ dbus_message_set_data(rawMessage, Slot, (IntPtr) rawThis, IntPtr.Zero);
+ }
+ }
+ }
+
+ public void Send(ref int serial)
+ {
+ if (!dbus_connection_send (Service.Connection.RawConnection, RawMessage, ref serial))
+ throw new OutOfMemoryException ();
+ }
+
+ public void Send()
+ {
+ int ignored = 0;
+ Send(ref ignored);
}
- public static Message Wrap (IntPtr ptr) {
- IntPtr gch_ptr;
+ public void SendWithReply()
+ {
+ IntPtr rawPendingCall = IntPtr.Zero;
- gch_ptr = dbus_message_get_data (ptr, wrapper_slot);
- if (gch_ptr != IntPtr.Zero) {
- return (DBus.Message) ((GCHandle)gch_ptr).Target;
- } else {
- return new Message (ptr);
- }
+ if (!dbus_connection_send_with_reply (Service.Connection.RawConnection, RawMessage, rawPendingCall, Service.Connection.Timeout))
+ throw new OutOfMemoryException();
}
+
+ public MethodReturn SendWithReplyAndBlock()
+ {
+ Error error = new Error();
+ error.Init();
- // surely there's a convention for this pattern with the property
- // and the real member
- IntPtr raw_;
- internal IntPtr raw {
- get {
- return raw_;
- }
- set {
- if (value == raw_)
- return;
-
- if (raw_ != IntPtr.Zero) {
- IntPtr gch_ptr;
-
- gch_ptr = dbus_message_get_data (raw_,
- wrapper_slot);
- Debug.Assert (gch_ptr != IntPtr.Zero);
-
- dbus_message_set_data (raw_, wrapper_slot,
- IntPtr.Zero, IntPtr.Zero);
-
- ((GCHandle) gch_ptr).Free ();
-
- dbus_message_unref (raw_);
- }
-
- raw_ = value;
-
- if (raw_ != IntPtr.Zero) {
- GCHandle gch;
-
- dbus_message_ref (raw_);
-
- // We store a weak reference to the C# object on the C object
- gch = GCHandle.Alloc (this, GCHandleType.WeakTrackResurrection);
-
- dbus_message_set_data (raw_, wrapper_slot,
- (IntPtr) gch, IntPtr.Zero);
- }
+ IntPtr rawMessage = dbus_connection_send_with_reply_and_block(Service.Connection.RawConnection,
+ RawMessage,
+ Service.Connection.Timeout,
+ ref error);
+
+ if (rawMessage != IntPtr.Zero) {
+ MethodReturn methodReturn = new MethodReturn(rawMessage, Service);
+ return methodReturn;
+ } else {
+ throw new DBusException(error);
}
}
- ~Message () {
- raw = IntPtr.Zero; // free the native object
+ public MessageType Type
+ {
+ get
+ {
+ return (MessageType) dbus_message_get_type(RawMessage);
+ }
}
- Message (IntPtr r) {
- raw = r;
+ public Service Service
+ {
+ set
+ {
+ if (this.service != null && (value.Name != this.service.Name)) {
+ if (!dbus_message_set_destination(RawMessage, value.Name)) {
+ throw new OutOfMemoryException();
+ }
+ }
+
+ this.service = value;
+ }
+ get
+ {
+ return this.service;
+ }
}
- // static constructor runs before any methods
- static Message () {
- DBus.Internals.Init ();
-
- Debug.Assert (wrapper_slot == -1);
-
- if (!dbus_message_allocate_data_slot (ref wrapper_slot))
- throw new OutOfMemoryException ();
+ protected virtual string PathName
+ {
+ set
+ {
+ if (value != this.pathName)
+ {
+ if (!dbus_message_set_path(RawMessage, value)) {
+ throw new OutOfMemoryException();
+ }
+
+ this.pathName = value;
+ }
+ }
+ get
+ {
+ if (this.pathName == null) {
+ this.pathName = Marshal.PtrToStringAnsi(dbus_message_get_path(RawMessage));
+ }
+
+ return this.pathName;
+ }
+ }
+
+ protected virtual string InterfaceName
+ {
+ set
+ {
+ if (value != this.interfaceName)
+ {
+ dbus_message_set_interface (RawMessage, value);
+ this.interfaceName = value;
+ }
+ }
+ get
+ {
+ if (this.interfaceName == null) {
+ this.interfaceName = Marshal.PtrToStringAnsi(dbus_message_get_interface(RawMessage));
+ }
- Debug.Assert (wrapper_slot >= 0);
+ return this.interfaceName;
+ }
}
+
+ protected virtual string Name
+ {
+ set
+ {
+ if (value != this.name)
+ {
+ dbus_message_set_member (RawMessage, value);
+ this.name = value;
+ }
+ }
+ get
+ {
+ if (this.name == null) {
+ this.name = Marshal.PtrToStringAnsi(dbus_message_get_member(RawMessage));
+ }
+
- // slot used to store the C# object on the C object
- static int wrapper_slot = -1;
+ return this.name;
+ }
+ }
+
+ public Arguments Arguments
+ {
+ get
+ {
+ if (this.arguments == null) {
+ this.arguments = new Arguments(this);
+ }
+
+ return this.arguments;
+ }
+ }
+
+ protected int Slot
+ {
+ get
+ {
+ if (slot == -1)
+ {
+ // We need to initialize the slot
+ if (!dbus_message_allocate_data_slot (ref slot))
+ throw new OutOfMemoryException ();
+
+ Debug.Assert (slot >= 0);
+ }
+
+ return slot;
+ }
+ }
+
+ [DllImport ("dbus-1", EntryPoint="dbus_message_new")]
+ protected extern static IntPtr dbus_message_new (int messageType);
+
+ [DllImport ("dbus-1", EntryPoint="dbus_message_unref")]
+ protected extern static void dbus_message_unref (IntPtr ptr);
+
+ [DllImport ("dbus-1", EntryPoint="dbus_message_ref")]
+ protected extern static void dbus_message_ref (IntPtr ptr);
+
+ [DllImport ("dbus-1", EntryPoint="dbus_message_allocate_data_slot")]
+ protected extern static bool dbus_message_allocate_data_slot (ref int slot);
+
+ [DllImport ("dbus-1", EntryPoint="dbus_message_free_data_slot")]
+ protected extern static void dbus_message_free_data_slot (ref int slot);
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_message_new")]
- private extern static IntPtr dbus_message_new (string name,
- string dest_service);
+ [DllImport ("dbus-1", EntryPoint="dbus_message_set_data")]
+ protected extern static bool dbus_message_set_data (IntPtr ptr,
+ int slot,
+ IntPtr data,
+ IntPtr free_data_func);
+
+ [DllImport ("dbus-1", EntryPoint="dbus_message_get_data")]
+ protected extern static IntPtr dbus_message_get_data (IntPtr ptr,
+ int slot);
+
+ [DllImport ("dbus-1", EntryPoint="dbus_connection_send")]
+ private extern static bool dbus_connection_send (IntPtr ptr,
+ IntPtr message,
+ ref int client_serial);
+
+ [DllImport ("dbus-1", EntryPoint="dbus_connection_send_with_reply")]
+ private extern static bool dbus_connection_send_with_reply (IntPtr rawConnection, IntPtr rawMessage, IntPtr rawPendingCall, int timeout);
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_message_unref")]
- private extern static void dbus_message_unref (IntPtr ptr);
+ [DllImport ("dbus-1", EntryPoint="dbus_connection_send_with_reply_and_block")]
+ private extern static IntPtr dbus_connection_send_with_reply_and_block (IntPtr rawConnection, IntPtr message, int timeout, ref Error error);
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_message_ref")]
- private extern static void dbus_message_ref (IntPtr ptr);
+ [DllImport("dbus-1")]
+ private extern static int dbus_message_get_type(IntPtr rawMessage);
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_message_get_name")]
- private extern static string dbus_message_get_name (IntPtr ptr);
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_set_path(IntPtr rawMessage, string pathName);
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_message_allocate_data_slot")]
- private extern static bool dbus_message_allocate_data_slot (ref int slot);
+ [DllImport("dbus-1")]
+ private extern static IntPtr dbus_message_get_path(IntPtr rawMessage);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_set_interface (IntPtr rawMessage, string interfaceName);
+
+ [DllImport("dbus-1")]
+ private extern static IntPtr dbus_message_get_interface(IntPtr rawMessage);
+
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_set_member (IntPtr rawMessage, string name);
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_message_free_data_slot")]
- private extern static void dbus_message_free_data_slot (ref int slot);
+ [DllImport("dbus-1")]
+ private extern static IntPtr dbus_message_get_member(IntPtr rawMessage);
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_message_set_data")]
- private extern static bool dbus_message_set_data (IntPtr ptr,
- int slot,
- IntPtr data,
- IntPtr free_data_func);
+ [DllImport("dbus-1")]
+ private extern static bool dbus_message_set_destination(IntPtr rawMessage, string serviceName);
- [DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_message_get_data")]
- private extern static IntPtr dbus_message_get_data (IntPtr ptr,
- int slot);
+ [DllImport("dbus-1")]
+ private extern static IntPtr dbus_message_get_destination(IntPtr rawMessage);
}
}
diff --git a/mono/MethodAttribute.cs b/mono/MethodAttribute.cs
new file mode 100644
index 00000000..db5da24e
--- /dev/null
+++ b/mono/MethodAttribute.cs
@@ -0,0 +1,12 @@
+using System;
+
+namespace DBus
+{
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=true)]
+ public class MethodAttribute : Attribute
+ {
+ public MethodAttribute()
+ {
+ }
+ }
+}
diff --git a/mono/MethodCall.cs b/mono/MethodCall.cs
new file mode 100644
index 00000000..ab7a4a36
--- /dev/null
+++ b/mono/MethodCall.cs
@@ -0,0 +1,80 @@
+namespace DBus
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics;
+
+ public class MethodCall : Message
+ {
+ public MethodCall() : base(MessageType.MethodCall)
+ {
+ }
+
+ internal MethodCall(IntPtr rawMessage, Service service) : base(rawMessage, service)
+ {
+ }
+
+ public MethodCall(Service service) : base(MessageType.MethodCall, service)
+ {
+ }
+
+ public MethodCall(Service service, string pathName, string interfaceName, string name)
+ {
+ this.service = service;
+
+ RawMessage = dbus_message_new_method_call(service.Name, pathName, interfaceName, name);
+
+ if (RawMessage == IntPtr.Zero) {
+ throw new OutOfMemoryException();
+ }
+
+ this.pathName = pathName;
+ this.interfaceName = interfaceName;
+ this.name = name;
+
+ dbus_message_unref(RawMessage);
+ }
+
+ public new string PathName
+ {
+ get
+ {
+ return base.PathName;
+ }
+
+ set
+ {
+ base.PathName = value;
+ }
+ }
+
+ public new string InterfaceName
+ {
+ get
+ {
+ return base.InterfaceName;
+ }
+
+ set
+ {
+ base.InterfaceName = value;
+ }
+ }
+
+ public new string Name
+ {
+ get
+ {
+ return base.Name;
+ }
+
+ set
+ {
+ base.Name = value;
+ }
+ }
+
+ [DllImport("dbus-1")]
+ private extern static IntPtr dbus_message_new_method_call(string serviceName, string pathName, string interfaceName, string name);
+ }
+}
diff --git a/mono/MethodReturn.cs b/mono/MethodReturn.cs
new file mode 100644
index 00000000..1e7731df
--- /dev/null
+++ b/mono/MethodReturn.cs
@@ -0,0 +1,57 @@
+namespace DBus
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics;
+
+ public class MethodReturn : Message
+ {
+ private MethodReturn() : base(MessageType.MethodReturn)
+ {
+ }
+
+ internal MethodReturn(IntPtr rawMessage, Service service) : base(rawMessage, service)
+ {
+ }
+
+ public MethodReturn(MethodCall methodCall)
+ {
+ this.service = methodCall.Service;
+
+ RawMessage = dbus_message_new_method_return(methodCall.RawMessage);
+
+ if (RawMessage == IntPtr.Zero) {
+ throw new OutOfMemoryException();
+ }
+
+ dbus_message_unref(RawMessage);
+ }
+
+ public new string PathName
+ {
+ get
+ {
+ return base.PathName;
+ }
+ }
+
+ public new string InterfaceName
+ {
+ get
+ {
+ return base.InterfaceName;
+ }
+ }
+
+ public new string Name
+ {
+ get
+ {
+ return base.Name;
+ }
+ }
+
+ [DllImport("dbus-1")]
+ private extern static IntPtr dbus_message_new_method_return(IntPtr rawMessage);
+ }
+}
diff --git a/mono/ProxyBuilder.cs b/mono/ProxyBuilder.cs
new file mode 100644
index 00000000..8e170c74
--- /dev/null
+++ b/mono/ProxyBuilder.cs
@@ -0,0 +1,301 @@
+namespace DBus
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics;
+ using System.Collections;
+ using System.Threading;
+ using System.Reflection;
+ using System.Reflection.Emit;
+
+ internal class ProxyBuilder
+ {
+ private Service service= null;
+ private string pathName = null;
+ private Type type = null;
+ private Introspector introspector = null;
+ private AssemblyBuilder proxyAssembly;
+
+ private static MethodInfo Service_NameMI = typeof(Service).GetMethod("get_Name",
+ new Type[0]);
+ private static MethodInfo Service_ConnectionMI = typeof(Service).GetMethod("get_Connection",
+ new Type[0]);
+ private static MethodInfo Message_ArgumentsMI = typeof(Message).GetMethod("get_Arguments",
+ new Type[0]);
+ private static MethodInfo Arguments_InitAppendingMI = typeof(Arguments).GetMethod("InitAppending",
+ new Type[0]);
+ private static MethodInfo Arguments_AppendMI = typeof(Arguments).GetMethod("Append",
+ new Type[] {typeof(DBusType.IDBusType)});
+ private static MethodInfo Message_SendWithReplyAndBlockMI = typeof(Message).GetMethod("SendWithReplyAndBlock",
+ new Type[0]);
+ private static MethodInfo Arguments_GetEnumeratorMI = typeof(Arguments).GetMethod("GetEnumerator",
+ new Type[0]);
+ private static MethodInfo IEnumerator_MoveNextMI = typeof(System.Collections.IEnumerator).GetMethod("MoveNext",
+ new Type[0]);
+ private static MethodInfo IEnumerator_CurrentMI = typeof(System.Collections.IEnumerator).GetMethod("get_Current",
+ new Type[0]);
+ private static MethodInfo Type_GetTypeFromHandleMI = typeof(System.Type).GetMethod("GetTypeFromHandle",
+ new Type[] {typeof(System.RuntimeTypeHandle)});
+ private static MethodInfo IDBusType_GetMI = typeof(DBusType.IDBusType).GetMethod("Get",
+ new Type[] {typeof(System.Type)});
+ private static ConstructorInfo MethodCall_C = typeof(MethodCall).GetConstructor(new Type[] {typeof(Service),
+ typeof(string),
+ typeof(string),
+ typeof(string)});
+
+
+
+ public ProxyBuilder(Service service, Type type, string pathName)
+ {
+ this.service = service;
+ this.pathName = pathName;
+ this.type = type;
+ this.introspector = new Introspector(type);
+ }
+
+ private void BuildMethod(MethodInfo method,
+ ref TypeBuilder typeB,
+ FieldInfo serviceF,
+ FieldInfo interfaceF,
+ FieldInfo pathF)
+ {
+ ParameterInfo[] pars = method.GetParameters();
+ Type[] parTypes = new Type[pars.Length];
+ for (int parN = 0; parN < pars.Length; parN++) {
+ parTypes[parN] = pars[parN].ParameterType;
+ }
+
+ // Generate the code
+ MethodBuilder methodBuilder = typeB.DefineMethod(method.Name,
+ MethodAttributes.Public |
+ MethodAttributes.HideBySig |
+ MethodAttributes.Virtual,
+ method.ReturnType,
+ parTypes);
+ ILGenerator generator = methodBuilder.GetILGenerator();
+
+ for (int parN = 0; parN < pars.Length; parN++) {
+ methodBuilder.DefineParameter(parN + 1, pars[parN].Attributes, pars[parN].Name);
+ }
+
+ // Generate the locals
+ LocalBuilder methodCallL = generator.DeclareLocal(typeof(MethodCall));
+ methodCallL.SetLocalSymInfo("methodCall");
+ LocalBuilder replyL = generator.DeclareLocal(typeof(MethodReturn));
+ replyL.SetLocalSymInfo("reply");
+ LocalBuilder enumeratorL = generator.DeclareLocal(typeof(System.Collections.IEnumerator));
+ enumeratorL.SetLocalSymInfo("enumerator");
+
+ if (method.ReturnType != typeof(void)) {
+ LocalBuilder retvalL = generator.DeclareLocal(method.ReturnType);
+ retvalL.SetLocalSymInfo("retval");
+ }
+
+ //generator.EmitWriteLine("MethodCall methodCall = new MethodCall(...)");
+ generator.Emit(OpCodes.Ldsfld, serviceF);
+ generator.Emit(OpCodes.Ldarg_0);
+ generator.Emit(OpCodes.Ldfld, pathF);
+ generator.Emit(OpCodes.Ldsfld, interfaceF);
+ generator.Emit(OpCodes.Ldstr, method.Name);
+ generator.Emit(OpCodes.Newobj, MethodCall_C);
+ generator.Emit(OpCodes.Stloc_0);
+
+ //generator.EmitWriteLine("methodCall.Arguments.InitAppending()");
+ generator.Emit(OpCodes.Ldloc_0);
+ generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
+ generator.EmitCall(OpCodes.Callvirt, Arguments_InitAppendingMI, null);
+
+ for (int parN = 0; parN < pars.Length; parN++) {
+ ParameterInfo par = pars[parN];
+ if (!par.IsOut) {
+ EmitIn(generator, par.ParameterType, parN);
+ }
+ }
+
+ //generator.EmitWriteLine("MethodReturn reply = methodCall.SendWithReplyAndBlock()");
+ generator.Emit(OpCodes.Ldloc_0);
+ generator.EmitCall(OpCodes.Callvirt, Message_SendWithReplyAndBlockMI, null);
+ generator.Emit(OpCodes.Stloc_1);
+
+ //generator.EmitWriteLine("IEnumerator enumeartor = reply.Arguments.GetEnumerator()");
+ generator.Emit(OpCodes.Ldloc_1);
+ generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
+ generator.EmitCall(OpCodes.Callvirt, Arguments_GetEnumeratorMI, null);
+ generator.Emit(OpCodes.Stloc_2);
+
+ // handle the return value
+ if (method.ReturnType != typeof(void)) {
+ EmitOut(generator, method.ReturnType, 0);
+ }
+
+ for (int parN = 0; parN < pars.Length; parN++) {
+ ParameterInfo par = pars[parN];
+ if (par.IsOut || par.ParameterType.ToString().EndsWith("&")) {
+ EmitOut(generator, par.ParameterType, parN);
+ }
+ }
+
+ if (method.ReturnType != typeof(void)) {
+ generator.Emit(OpCodes.Ldloc_3);
+ }
+
+ generator.Emit(OpCodes.Ret);
+
+ // Generate the method
+ typeB.DefineMethodOverride(methodBuilder, method);
+ }
+
+ private void EmitIn(ILGenerator generator, Type parType, int parN)
+ {
+ Type inParType = Arguments.MatchType(parType);
+ //generator.EmitWriteLine("methodCall.Arguments.Append(...)");
+ generator.Emit(OpCodes.Ldloc_0);
+ generator.EmitCall(OpCodes.Callvirt, Message_ArgumentsMI, null);
+ generator.Emit(OpCodes.Ldarg_S, parN + 1);
+
+ // Call the DBusType EmitMarshalIn to make it emit itself
+ object[] pars = new object[] {generator, parType};
+ inParType.InvokeMember("EmitMarshalIn", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, pars, null);
+
+ generator.Emit(OpCodes.Newobj, Arguments.GetDBusTypeConstructor(inParType, parType));
+ generator.EmitCall(OpCodes.Callvirt, Arguments_AppendMI, null);
+ }
+
+ private void EmitOut(ILGenerator generator, Type parType, int parN)
+ {
+ Type outParType = Arguments.MatchType(parType);
+ //generator.EmitWriteLine("enumerator.MoveNext()");
+ generator.Emit(OpCodes.Ldloc_2);
+ generator.EmitCall(OpCodes.Callvirt, IEnumerator_MoveNextMI, null);
+
+ //generator.EmitWriteLine("return (" + parType + ") ((DBusType.IDBusType) enumerator.Current).Get(typeof(" + parType + "))");
+ generator.Emit(OpCodes.Pop);
+ if (parN > 0) {
+ generator.Emit(OpCodes.Ldarg_S, parN + 1);
+ }
+
+ generator.Emit(OpCodes.Ldloc_2);
+ generator.EmitCall(OpCodes.Callvirt, IEnumerator_CurrentMI, null);
+ generator.Emit(OpCodes.Castclass, typeof(DBusType.IDBusType));
+ generator.Emit(OpCodes.Ldtoken, parType);
+ generator.EmitCall(OpCodes.Call, Type_GetTypeFromHandleMI, null);
+ generator.EmitCall(OpCodes.Callvirt, IDBusType_GetMI, null);
+
+ // Call the DBusType EmitMarshalOut to make it emit itself
+ object[] pars = new object[] {generator, parType, parN == 0};
+ outParType.InvokeMember("EmitMarshalOut", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, pars, null);
+
+ if (parN == 0) {
+ generator.Emit(OpCodes.Stloc_3);
+ }
+ }
+
+ public void BuildConstructor(ref TypeBuilder typeB, FieldInfo serviceF, FieldInfo interfaceF, FieldInfo pathF)
+ {
+ Type[] pars = {typeof(Service), typeof(string), typeof(string)};
+ ConstructorBuilder constructor = typeB.DefineConstructor(MethodAttributes.RTSpecialName |
+ MethodAttributes.Public,
+ CallingConventions.Standard, pars);
+
+ ILGenerator generator = constructor.GetILGenerator();
+ generator.Emit(OpCodes.Ldarg_0);
+ generator.Emit(OpCodes.Call, this.introspector.Constructor);
+ generator.Emit(OpCodes.Ldarg_1);
+ generator.Emit(OpCodes.Stsfld, serviceF);
+ generator.Emit(OpCodes.Ldarg_2);
+ generator.Emit(OpCodes.Stsfld, interfaceF);
+ generator.Emit(OpCodes.Ldarg_0);
+ generator.Emit(OpCodes.Ldarg_3);
+ generator.Emit(OpCodes.Stfld, pathF);
+
+ generator.Emit(OpCodes.Ret);
+ }
+
+ public object GetProxy()
+ {
+
+ // Build the type
+ TypeBuilder typeB = ServiceModuleBuilder.DefineType(ProxyName, TypeAttributes.Public, this.type);
+ //type.AddInterfaceImplementation(typeof(IProxy));
+
+ FieldBuilder serviceF = typeB.DefineField("service",
+ typeof(Service),
+ FieldAttributes.Private |
+ FieldAttributes.Static);
+ FieldBuilder interfaceF = typeB.DefineField("interfaceName",
+ typeof(string),
+ FieldAttributes.Private |
+ FieldAttributes.Static);
+ FieldBuilder pathF = typeB.DefineField("pathName",
+ typeof(string),
+ FieldAttributes.Private);
+
+ BuildConstructor(ref typeB, serviceF, interfaceF, pathF);
+
+ // Build the methods
+ foreach (MethodInfo method in this.introspector.Methods) {
+ BuildMethod(method, ref typeB, serviceF, interfaceF, pathF);
+ }
+
+ Type [] parTypes = new Type[] {typeof(Service), typeof(string), typeof(string)};
+ object [] pars = new object[] {Service, this.introspector.InterfaceName, pathName};
+
+ Type proxyType = typeB.CreateType();
+
+ // Uncomment the following line to produce a DLL of the
+ // constructed assembly which can then be examined using
+ // monodis. Note that in order for this to work you should copy
+ // the client assembly as a dll file so that monodis can pick it
+ // up.
+ //ProxyAssembly.Save("proxy.dll");
+
+ ConstructorInfo constructor = proxyType.GetConstructor(parTypes);
+ object instance = constructor.Invoke(pars);
+ return instance;
+ }
+
+ private ModuleBuilder ServiceModuleBuilder
+ {
+ get
+ {
+ if (Service.module == null) {
+ Service.module = ProxyAssembly.DefineDynamicModule(Service.Name, "proxy.dll", true);
+ }
+
+ return Service.module;
+ }
+ }
+
+ private Service Service
+ {
+ get
+ {
+ return this.service;
+ }
+ }
+
+ private string ProxyName
+ {
+ get
+ {
+ return this.introspector.InterfaceName + ".Proxy";
+ }
+ }
+
+ private AssemblyBuilder ProxyAssembly
+ {
+ get
+ {
+ if (this.proxyAssembly == null){
+ AssemblyName assemblyName = new AssemblyName();
+ assemblyName.Name = "DBusProxy";
+ this.proxyAssembly = Thread.GetDomain().DefineDynamicAssembly(assemblyName,
+ AssemblyBuilderAccess.RunAndSave);
+ }
+
+ return this.proxyAssembly;
+ }
+ }
+ }
+}
+
diff --git a/mono/README b/mono/README
new file mode 100644
index 00000000..2d1b08b6
--- /dev/null
+++ b/mono/README
@@ -0,0 +1,118 @@
+D-BUS Mono Bindings
+===
+
+These bindings are a 'thick' wrapper around the D-BUS API. For now
+they rely on the main loop provided by the GLib bindings but this
+dependancy will be removed in the near future.
+
+The wrapper serves two main functions: firstly, it has the know-how to
+introspect live objects passed to it by a server and service requests
+to those objects via the D-BUS. Secondly, it can create a proxy for
+clients who can pretend they are making calls to the regular
+objects. This latter piece of magic is implemented using
+Reflection.Emit to create an assembly on-the-fly containing
+sub-classes of the classes the client thinks it's really using. These
+sub-classes simply marshal each method's parameters off to the D-BUS,
+demarshal the results and return them to the client as if nothing
+happened.
+
+Usage
+===
+
+A server do should something like this:
+
+ namespace Foo
+ {
+ using System;
+ using DBus;
+ using Gtk;
+
+ public class MyServer
+ {
+ public static int Main(string [] args)
+ {
+ Application.Init();
+
+1 Connection connection = Bus.GetSessionBus();
+2 Service service = new Service(connection, "org.foo");
+3 MyObject myObject = new MyObject();
+4 service.RegisterObject(myObject, "/org/foo/MyObject");
+
+ Application.Run();
+
+ return 0;
+ }
+ }
+ }
+
+In line 1 we get a connection to the session bus. Then, in line 2 we
+create a service which will listen for requests to org.foo to
+service. In line 3 we create a MyObject object and register it with an
+object path in line 4. It's almost that simple. All that's missing is
+to mark MyObject in such a way that dbus-sharp knows how to export
+it. This is done using the attributes, Interface and Method,
+as in the following example:
+
+ namespace Foo
+ {
+ using System;
+ using DBus;
+
+ [Interface("org.foo.MyObject")]
+ public class MyObject
+ {
+ [Method]
+ public virtual string Echo(string message)
+ {
+ return "Reply: " + message;
+ }
+ }
+ }
+
+Note that the Methods should also be declared virtual in order for
+the client to use same class declaration.
+
+Now for the client:
+
+ namespace Foo
+ {
+ using System;
+ using DBus;
+
+ public class MyClient
+ {
+ public static int Main(string [] args)
+ {
+1 Connection connection = Bus.GetSessionBus();
+2 Service service = Service.Get(connection, "org.foo");
+3 MyObject myObject = (MyObject)
+ service.GetObject(typeof(MyObject), "/org/foo/MyObject");
+4 System.Console.WriteLine(testObject.Echo("Hello world!"));
+
+ return 0;
+ }
+ }
+ }
+
+Here we start off the same by getting a connection to the session
+bus. This time though, in line 2, we get the existing service rather
+than creating it. In line 3, we ask the service to get the object
+"/org/foo/MyObject" as registered by the server and that return it as
+a MyObject. Once obtained we can use it like any normal object as in
+line 4. This supposes, of course, that you've just written MyObject
+and happen to have it readily available. If that were not the case,
+for example if you wanted to call a method on one of the well-known
+services, then you will need to write a stub class, like the MyObject
+class above, which has the method calls you need correctly defined but
+needn't actually have any implementation.
+
+
+Working Example
+===
+
+The example directory contains a working example similar to that
+described above. It uses the session bus so first run dbus-launch and
+then export DBUS_SESSION_BUS_ADDRESS, as displayed by dbus-launch, to
+two terminals, one to run the server and one for the client. Then,
+start the server in one terminal, the client in the other and cross
+your fingers.
diff --git a/mono/Server.cs b/mono/Server.cs
new file mode 100644
index 00000000..e39b7ca2
--- /dev/null
+++ b/mono/Server.cs
@@ -0,0 +1,148 @@
+namespace DBus
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics;
+
+ public class Server
+ {
+ private IntPtr rawServer;
+
+ /// <summary>
+ /// The current slot number
+ /// </summary>
+ private static int slot = -1;
+
+ private string address = null;
+
+ private Server(IntPtr rawServer)
+ {
+ RawServer = rawServer;
+ }
+
+ public Server(string address)
+ {
+ Error error = new Error();
+ error.Init();
+ RawServer = dbus_server_listen(address, ref error);
+ if (RawServer != IntPtr.Zero){
+ dbus_server_unref(RawServer);
+ } else {
+ throw new DBusException(error);
+ }
+ }
+
+ ~Server()
+ {
+ if (RawServer != IntPtr.Zero) {
+ dbus_server_unref(rawServer);
+ }
+
+ RawServer = IntPtr.Zero;
+ }
+
+ public string Address
+ {
+ get
+ {
+ if (address == null) {
+ address = dbus_server_get_address(rawServer);
+ }
+
+ return address;
+ }
+ }
+
+ private int Slot
+ {
+ get
+ {
+ if (slot == -1)
+ {
+ // We need to initialize the slot
+ if (!dbus_server_allocate_data_slot (ref slot))
+ throw new OutOfMemoryException ();
+
+ Debug.Assert (slot >= 0);
+ }
+
+ return slot;
+ }
+ }
+
+ internal IntPtr RawServer
+ {
+ get
+ {
+ return rawServer;
+ }
+ set
+ {
+ if (value == rawServer)
+ return;
+
+ if (rawServer != IntPtr.Zero)
+ {
+ // Get the reference to this
+ IntPtr rawThis = dbus_server_get_data (rawServer, Slot);
+ Debug.Assert (rawThis != IntPtr.Zero);
+
+ // Blank over the reference
+ dbus_server_set_data (rawServer, Slot, IntPtr.Zero, IntPtr.Zero);
+
+ // Free the reference
+ ((GCHandle) rawThis).Free();
+
+ // Unref the connection
+ dbus_server_unref(rawServer);
+ }
+
+ this.rawServer = value;
+
+ if (rawServer != IntPtr.Zero)
+ {
+ GCHandle rawThis;
+
+ dbus_server_ref (rawServer);
+
+ // We store a weak reference to the C# object on the C object
+ rawThis = GCHandle.Alloc (this, GCHandleType.WeakTrackResurrection);
+
+ dbus_server_set_data(rawServer, Slot, (IntPtr) rawThis, IntPtr.Zero);
+ }
+ }
+ }
+
+ [DllImport ("dbus-1", EntryPoint="dbus_server_listen")]
+ private extern static IntPtr dbus_server_listen(string address, ref Error error);
+
+ [DllImport ("dbus-1", EntryPoint="dbus_server_unref")]
+ private extern static IntPtr dbus_server_unref(IntPtr rawServer);
+
+ [DllImport ("dbus-1", EntryPoint="dbus_server_ref")]
+ private extern static void dbus_server_ref(IntPtr rawServer);
+
+ [DllImport ("dbus-1", EntryPoint="dbus_server_disconnect")]
+ private extern static void dbus_server_disconnect(IntPtr rawServer);
+
+ [DllImport ("dbus-1", EntryPoint="dbus_server_get_address")]
+ private extern static string dbus_server_get_address(IntPtr rawServer);
+
+ [DllImport ("dbus-1", EntryPoint="dbus_server_set_data")]
+ private extern static bool dbus_server_set_data(IntPtr rawServer,
+ int slot,
+ IntPtr data,
+ IntPtr freeDataFunc);
+
+ [DllImport ("dbus-1", EntryPoint="dbus_server_get_data")]
+ private extern static IntPtr dbus_server_get_data(IntPtr rawServer,
+ int slot);
+
+ [DllImport ("dbus-1", EntryPoint="dbus_server_allocate_data_slot")]
+ private extern static bool dbus_server_allocate_data_slot (ref int slot);
+
+ [DllImport ("dbus-1", EntryPoint="dbus_server_free_data_slot")]
+ private extern static void dbus_server_free_data_slot (ref int slot);
+
+ }
+}
diff --git a/mono/Service.cs b/mono/Service.cs
new file mode 100644
index 00000000..a3c2a31f
--- /dev/null
+++ b/mono/Service.cs
@@ -0,0 +1,115 @@
+namespace DBus
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics;
+ using System.Collections;
+ using System.Reflection;
+ using System.Reflection.Emit;
+
+ public class Service
+ {
+ private Connection connection;
+ private string name;
+ private bool local = false;
+ private Hashtable registeredHandlers = new Hashtable();
+ internal ModuleBuilder module = null;
+
+ internal Service(string name, Connection connection)
+ {
+ this.name = name;
+ this.connection = connection;
+ }
+
+ public Service(Connection connection, string name)
+ {
+ Error error = new Error();
+ error.Init();
+
+ // This isn't used for now
+ uint flags = 0;
+
+ if (dbus_bus_acquire_service(connection.RawConnection, name, flags, ref error) == -1) {
+ throw new DBusException(error);
+ }
+
+ this.connection = connection;
+ this.name = name;
+ this.local = true;
+ }
+
+ public static bool Exists(Connection connection, string name)
+ {
+ Error error = new Error();
+ error.Init();
+
+ if (dbus_bus_service_exists(connection.RawConnection,
+ name,
+ ref error)) {
+ return true;
+ } else {
+ if (error.IsSet) {
+ throw new DBusException(error);
+ }
+ return false;
+ }
+ }
+
+ public static Service Get(Connection connection, string name)
+ {
+ if (Exists(connection, name)) {
+ return new Service(name, connection);
+ } else {
+ throw new ApplicationException("Service '" + name + "' does not exist.");
+ }
+ }
+
+ public void RegisterObject(object handledObject,
+ string pathName)
+ {
+ Handler handler = new Handler(handledObject,
+ pathName,
+ this);
+ registeredHandlers.Add(handledObject, handler);
+ }
+
+ internal Handler GetHandler(object handledObject)
+ {
+ return (Handler) registeredHandlers[handledObject];
+ }
+
+ public object GetObject(Type type, string pathName)
+ {
+ ProxyBuilder builder = new ProxyBuilder(this, type, pathName);
+ object proxy = builder.GetProxy();
+ return proxy;
+ }
+
+ public string Name
+ {
+ get
+ {
+ return this.name;
+ }
+ }
+
+ public Connection Connection
+ {
+ get
+ {
+ return connection;
+ }
+
+ set
+ {
+ this.connection = value;
+ }
+ }
+
+ [DllImport ("dbus-1")]
+ private extern static int dbus_bus_acquire_service (IntPtr rawConnection, string serviceName, uint flags, ref Error error);
+
+ [DllImport ("dbus-1")]
+ private extern static bool dbus_bus_service_exists (IntPtr rawConnection, string serviceName, ref Error error);
+ }
+}
diff --git a/mono/Signal.cs b/mono/Signal.cs
new file mode 100644
index 00000000..a9209fec
--- /dev/null
+++ b/mono/Signal.cs
@@ -0,0 +1,60 @@
+namespace DBus
+{
+ using System;
+ using System.Runtime.InteropServices;
+ using System.Diagnostics;
+
+ public class Signal : Message
+ {
+ public Signal() : base(MessageType.Signal)
+ {
+ }
+
+ internal Signal(IntPtr rawMessage, Service service) : base(rawMessage, service)
+ {
+ }
+
+ public Signal(Service service) : base(MessageType.Signal, service)
+ {
+ }
+
+ public new string PathName
+ {
+ get
+ {
+ return base.PathName;
+ }
+
+ set
+ {
+ base.PathName = value;
+ }
+ }
+
+ public new string InterfaceName
+ {
+ get
+ {
+ return base.InterfaceName;
+ }
+
+ set
+ {
+ base.InterfaceName = value;
+ }
+ }
+
+ public new string Name
+ {
+ get
+ {
+ return base.Name;
+ }
+
+ set
+ {
+ base.Name = value;
+ }
+ }
+ }
+}
diff --git a/mono/TODO b/mono/TODO
new file mode 100644
index 00000000..e44c2a92
--- /dev/null
+++ b/mono/TODO
@@ -0,0 +1,8 @@
+- Clean up memory leakages. Call _unref functions etc.
+
+- Convert strings to/from UTF-8
+
+- Implement own main loop. The current implementation depends on the
+ GLib mainloop.
+
+- Get test working. Probably a threading issue.
diff --git a/mono/Test.cs b/mono/Test.cs
index e92176f2..028986c9 100644
--- a/mono/Test.cs
+++ b/mono/Test.cs
@@ -1,53 +1,70 @@
-
using System;
-using System.Runtime.InteropServices;
+using System.Threading;
+using DBus;
+using Gtk;
-class Test {
- static void Main() {
- g_thread_init (IntPtr.Zero);
+namespace DBus.Test
+{
+ public class Test
+ {
+ public static Service service = null;
+ public static Connection connection = null;
- DBus.Connection c;
+ public static int Main(string [] args)
+ {
+ TestServer testServer = new TestServer();
+ Thread serverThread = new Thread(new ThreadStart(testServer.StartServer));
+ serverThread.Start();
- // c = new DBus.Connection ("unix:path=/tmp/foobar");
+ connection = Bus.GetSessionBus();
+ service = Service.Get(connection, "org.freedesktop.Test");
- try {
- c = DBus.Connection.GetBus (DBus.Connection.BusType.Session);
- }
- catch (DBus.Exception e) {
- Console.Error.WriteLine ("Failed to open connection: {0}",
- e.Message);
- return;
- }
+ TestObject testObject = (TestObject) service.GetObject(typeof(TestObject), "/org/freedesktop/Test/TestObject");
- DBus.Message m = new DBus.Message ("org.freedesktop.Foo",
- "org.freedesktop.DBus.Broadcast");
+ System.Console.WriteLine(testObject.Test1("Hello"));
- c.Send (m);
- c.Flush ();
+ //RunTests(testObject);
- IntPtr loop = g_main_loop_new (IntPtr.Zero, false);
-
- g_main_loop_run (loop);
+ return 0;
+ }
- g_main_loop_unref (loop);
+ public static void RunTests(TestObject testObject)
+ {
+ System.Console.WriteLine(testObject.Test1("Hello"));
+ }
}
- internal const string GLibname = "libglib-2.0.so.0";
- internal const string GThreadname = "libgthread-2.0.so.0";
-
- [DllImport (GLibname, EntryPoint="g_main_loop_new")]
- private extern static IntPtr g_main_loop_new (IntPtr context,
- bool is_running);
+ public class TestServer
+ {
+ public Connection connection;
+ public Service service;
- [DllImport (GLibname, EntryPoint="g_main_loop_unref")]
- private extern static void g_main_loop_unref (IntPtr loop);
+ public TestServer()
+ {
+ Application.Init();
+
+ System.Console.WriteLine("Starting server...");
- [DllImport (GLibname, EntryPoint="g_main_loop_run")]
- private extern static void g_main_loop_run (IntPtr loop);
+ connection = Bus.GetSessionBus();
+ service = new Service(connection, "org.freedesktop.Test");
+ TestObject testObject = new TestObject();
+ service.RegisterObject(testObject, "/org/freedesktop/Test/TestObject");
+ }
+
+ public void StartServer()
+ {
+ Application.Run();
+ }
+ }
- [DllImport (GLibname, EntryPoint="g_main_loop_quit")]
- private extern static void g_main_loop_quit (IntPtr loop);
-
- [DllImport (GThreadname, EntryPoint="g_thread_init")]
- private extern static void g_thread_init (IntPtr vtable);
+ [Interface("org.freedesktop.Test.TestObject")]
+ public class TestObject
+ {
+ [Method]
+ public virtual int Test1(string x)
+ {
+ System.Console.WriteLine("Called: " + x);
+ return 5;
+ }
+ }
}
diff --git a/mono/example/EchoClient.cs b/mono/example/EchoClient.cs
new file mode 100644
index 00000000..dc20771a
--- /dev/null
+++ b/mono/example/EchoClient.cs
@@ -0,0 +1,19 @@
+namespace Foo
+{
+ using System;
+ using DBus;
+
+ public class EchoClient
+ {
+ public static int Main(string [] args)
+ {
+ Connection connection = Bus.GetSessionBus();
+ Service service = Service.Get(connection, "org.freedesktop.Test");
+ Echoer echoer = (Echoer)
+ service.GetObject(typeof(Echoer), "/org/freedesktop/Test/Echoer");
+ System.Console.WriteLine(echoer.Echo("Hello world!"));
+
+ return 0;
+ }
+ }
+}
diff --git a/mono/example/EchoServer.cs b/mono/example/EchoServer.cs
new file mode 100644
index 00000000..243a2730
--- /dev/null
+++ b/mono/example/EchoServer.cs
@@ -0,0 +1,23 @@
+namespace Foo
+{
+ using System;
+ using DBus;
+ using Gtk;
+
+ public class EchoServer
+ {
+ public static int Main(string [] args)
+ {
+ Application.Init();
+
+ Connection connection = Bus.GetSessionBus();
+ Service service = new Service(connection, "org.freedesktop.Test");
+ Echoer echoer = new Echoer();
+ service.RegisterObject(echoer, "/org/freedesktop/Test/Echoer");
+
+ Application.Run();
+
+ return 0;
+ }
+ }
+}
diff --git a/mono/example/Echoer.cs b/mono/example/Echoer.cs
new file mode 100644
index 00000000..bc5a843d
--- /dev/null
+++ b/mono/example/Echoer.cs
@@ -0,0 +1,16 @@
+namespace Foo
+{
+ using System;
+ using DBus;
+
+ [Interface("org.freedesktop.Test.Echoer")]
+ public class Echoer
+ {
+ [Method]
+ public virtual string Echo(string message)
+ {
+ System.Console.WriteLine("I received: " + message);
+ return "Reply: " + message;
+ }
+ }
+}
diff --git a/mono/example/Makefile.am b/mono/example/Makefile.am
new file mode 100644
index 00000000..2355bf31
--- /dev/null
+++ b/mono/example/Makefile.am
@@ -0,0 +1,19 @@
+DESTDIR=
+
+NOINST_EXES=echo-server.exe echo-client.exe
+
+all: $(NOINST_EXES)
+
+echo-server.exe: EchoServer.cs Echoer.cs
+ $(MCS) $(MCSFLAGS) --unsafe --target exe -L .. -r dbus-sharp.dll -r gtk-sharp -o echo-server.exe EchoServer.cs Echoer.cs
+
+echo-client.exe: EchoClient.cs Echoer.cs
+ $(MCS) $(MCSFLAGS) --unsafe --target exe -L .. -r dbus-sharp.dll -o echo-client.exe EchoClient.cs Echoer.cs
+
+clean:
+ rm -f $(NOINST_EXES)
+
+install: all
+
+EXTRA_DIST=EchoServer.cs EchoClient.cs Echoer.cs
+