First checkin of the Mono bindings.

This commit is contained in:
Owen Fraser-Green 2004-03-23 12:10:32 +00:00
parent 2195cf0dbd
commit c916037773
44 changed files with 3652 additions and 343 deletions

View file

@ -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

View file

@ -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

View file

@ -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}

8
dbus-sharp.pc.in Normal file
View file

@ -0,0 +1,8 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
Name: DBus#
Description: DBus# - D-BUS .NET Bindings
Version: 0.1

304
mono/Arguments.cs Normal file
View file

@ -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);
}
}

51
mono/Bus.cs Normal file
View file

@ -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);
}
}

View file

@ -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);
SetupWithMain();
}
// Keep in sync with C
public enum BusType {
Session = 0,
System = 1,
Activation = 2
}
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);
}
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);
}
}
// 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);
}
}
}
~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.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 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-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);
}
}

18
mono/Custom.cs Normal file
View file

@ -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;
}
}
}

View file

@ -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 ();
}
}

12
mono/DBusException.cs Normal file
View file

@ -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();
}
}
}

130
mono/DBusType/Array.cs Normal file
View file

@ -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);
}
}

86
mono/DBusType/Boolean.cs Normal file
View file

@ -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);
}
}

86
mono/DBusType/Byte.cs Normal file
View file

@ -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);
}
}

109
mono/DBusType/Custom.cs Normal file
View file

@ -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);
}
}

145
mono/DBusType/Dict.cs Normal file
View file

@ -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);
}
}

86
mono/DBusType/Double.cs Normal file
View file

@ -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);
}
}

View file

@ -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);
}
}

86
mono/DBusType/Int32.cs Normal file
View file

@ -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);
}
}

86
mono/DBusType/Int64.cs Normal file
View file

@ -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);
}
}

68
mono/DBusType/Nil.cs Normal file
View file

@ -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);
}
}

110
mono/DBusType/ObjectPath.cs Normal file
View file

@ -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);
}
}

86
mono/DBusType/String.cs Normal file
View file

@ -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);
}
}

87
mono/DBusType/UInt32.cs Normal file
View file

@ -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);
}
}

87
mono/DBusType/UInt64.cs Normal file
View file

@ -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);
}
}

View file

@ -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;
public void Init()
{
dbus_error_init(ref this);
}
public void Free()
{
dbus_error_free(ref this);
}
public string Message
{
get
{
return System.Runtime.InteropServices.Marshal.PtrToStringAnsi(message);
}
}
public string Name
{
get
{
return System.Runtime.InteropServices.Marshal.PtrToStringAnsi(name);
}
}
internal void Init () {
dbus_error_init (ref this);
public bool IsSet
{
get
{
return (name != IntPtr.Zero);
}
}
internal void Free () {
dbus_error_free (ref this);
}
[DllImport (DBus.Internals.DBusLibname, EntryPoint="dbus_error_init")]
[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);
}
}

256
mono/Handler.cs Normal file
View file

@ -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);
}
}

View file

@ -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;
}
}
}
}

106
mono/Introspector.cs Normal file
View file

@ -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;
}
}
}
}
}
}

View file

@ -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)

View file

@ -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);
}
public string Name {
get {
return dbus_message_get_name (raw);
}
}
public static Message Wrap (IntPtr ptr) {
IntPtr gch_ptr;
RawMessage = dbus_message_new((int) messageType);
gch_ptr = dbus_message_get_data (ptr, wrapper_slot);
if (gch_ptr != IntPtr.Zero) {
return (DBus.Message) ((GCHandle)gch_ptr).Target;
if (RawMessage == IntPtr.Zero) {
throw new OutOfMemoryException();
}
dbus_message_unref(RawMessage);
}
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 void SendWithReply()
{
IntPtr rawPendingCall = IntPtr.Zero;
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();
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 {
return new Message (ptr);
throw new DBusException(error);
}
}
// 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);
}
}
}
~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));
}
return this.name;
}
}
// slot used to store the C# object on the C object
static int wrapper_slot = -1;
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.Internals.DBusLibname, EntryPoint="dbus_message_new")]
private extern static IntPtr dbus_message_new (string name,
string dest_service);
[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-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.Internals.DBusLibname, EntryPoint="dbus_message_unref")]
private extern static void dbus_message_unref (IntPtr ptr);
[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_ref")]
private extern static void dbus_message_ref (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_get_name")]
private extern static string dbus_message_get_name (IntPtr ptr);
[DllImport("dbus-1")]
private extern static int dbus_message_get_type(IntPtr rawMessage);
[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 bool dbus_message_set_path(IntPtr rawMessage, string pathName);
[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_path(IntPtr rawMessage);
[DllImport("dbus-1")]
private extern static bool dbus_message_set_interface (IntPtr rawMessage, string interfaceName);
[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 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_get_data")]
private extern static IntPtr dbus_message_get_data (IntPtr ptr,
int slot);
[DllImport("dbus-1")]
private extern static IntPtr dbus_message_get_member(IntPtr rawMessage);
[DllImport("dbus-1")]
private extern static bool dbus_message_set_destination(IntPtr rawMessage, string serviceName);
[DllImport("dbus-1")]
private extern static IntPtr dbus_message_get_destination(IntPtr rawMessage);
}
}

12
mono/MethodAttribute.cs Normal file
View file

@ -0,0 +1,12 @@
using System;
namespace DBus
{
[AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=true)]
public class MethodAttribute : Attribute
{
public MethodAttribute()
{
}
}
}

80
mono/MethodCall.cs Normal file
View file

@ -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);
}
}

57
mono/MethodReturn.cs Normal file
View file

@ -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);
}
}

301
mono/ProxyBuilder.cs Normal file
View file

@ -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;
}
}
}
}

118
mono/README Normal file
View file

@ -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.

148
mono/Server.cs Normal file
View file

@ -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);
}
}

115
mono/Service.cs Normal file
View file

@ -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);
}
}

60
mono/Signal.cs Normal file
View file

@ -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;
}
}
}
}

8
mono/TODO Normal file
View file

@ -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.

View file

@ -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);
return 0;
}
g_main_loop_run (loop);
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;
}
}
}

View file

@ -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;
}
}
}

View file

@ -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;
}
}
}

16
mono/example/Echoer.cs Normal file
View file

@ -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;
}
}
}

19
mono/example/Makefile.am Normal file
View file

@ -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