mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-05-05 02:58:01 +02:00
First checkin of the Mono bindings.
This commit is contained in:
parent
2195cf0dbd
commit
c916037773
44 changed files with 3652 additions and 343 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
8
dbus-sharp.pc.in
Normal 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
304
mono/Arguments.cs
Normal 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
51
mono/Bus.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
18
mono/Custom.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
mono/DBus.cs
24
mono/DBus.cs
|
|
@ -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
12
mono/DBusException.cs
Normal 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
130
mono/DBusType/Array.cs
Normal 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
86
mono/DBusType/Boolean.cs
Normal 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
86
mono/DBusType/Byte.cs
Normal 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
109
mono/DBusType/Custom.cs
Normal 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
145
mono/DBusType/Dict.cs
Normal 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
86
mono/DBusType/Double.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
16
mono/DBusType/IDBusType.cs
Normal file
16
mono/DBusType/IDBusType.cs
Normal 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
86
mono/DBusType/Int32.cs
Normal 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
86
mono/DBusType/Int64.cs
Normal 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
68
mono/DBusType/Nil.cs
Normal 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
110
mono/DBusType/ObjectPath.cs
Normal 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
86
mono/DBusType/String.cs
Normal 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
87
mono/DBusType/UInt32.cs
Normal 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
87
mono/DBusType/UInt64.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
256
mono/Handler.cs
Normal 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);
|
||||
|
||||
}
|
||||
}
|
||||
23
mono/InterfaceAttribute.cs
Normal file
23
mono/InterfaceAttribute.cs
Normal 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
106
mono/Introspector.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
429
mono/Message.cs
429
mono/Message.cs
|
|
@ -1,129 +1,358 @@
|
|||
namespace DBus {
|
||||
namespace DBus
|
||||
{
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Diagnostics;
|
||||
using System.Collections;
|
||||
|
||||
public class Message {
|
||||
public class Message
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// A pointer to the underlying Message structure
|
||||
/// </summary>
|
||||
private IntPtr rawMessage;
|
||||
|
||||
/// <summary>
|
||||
/// The current slot number
|
||||
/// </summary>
|
||||
private static int slot = -1;
|
||||
|
||||
// Keep in sync with C
|
||||
public enum MessageType
|
||||
{
|
||||
Invalid = 0,
|
||||
MethodCall = 1,
|
||||
MethodReturn = 2,
|
||||
Error = 3,
|
||||
Signal = 4
|
||||
}
|
||||
|
||||
public Message (string name,
|
||||
string dest_service) {
|
||||
private Arguments arguments = null;
|
||||
|
||||
protected Service service = null;
|
||||
protected string pathName = null;
|
||||
protected string interfaceName = null;
|
||||
protected string name = null;
|
||||
|
||||
protected Message()
|
||||
{
|
||||
// An empty constructor for the sake of sub-classes which know how to construct theirselves.
|
||||
}
|
||||
|
||||
protected Message(IntPtr rawMessage, Service service)
|
||||
{
|
||||
RawMessage = rawMessage;
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
protected Message(MessageType messageType)
|
||||
{
|
||||
// the assignment bumps the refcount
|
||||
raw = dbus_message_new (name, dest_service);
|
||||
if (raw == IntPtr.Zero)
|
||||
throw new OutOfMemoryException ();
|
||||
dbus_message_unref (raw);
|
||||
}
|
||||
|
||||
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
12
mono/MethodAttribute.cs
Normal 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
80
mono/MethodCall.cs
Normal 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
57
mono/MethodReturn.cs
Normal 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
301
mono/ProxyBuilder.cs
Normal 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
118
mono/README
Normal 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
148
mono/Server.cs
Normal 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
115
mono/Service.cs
Normal 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
60
mono/Signal.cs
Normal 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
8
mono/TODO
Normal 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.
|
||||
93
mono/Test.cs
93
mono/Test.cs
|
|
@ -1,53 +1,70 @@
|
|||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using DBus;
|
||||
using Gtk;
|
||||
|
||||
class Test {
|
||||
static void Main() {
|
||||
g_thread_init (IntPtr.Zero);
|
||||
namespace DBus.Test
|
||||
{
|
||||
public class Test
|
||||
{
|
||||
public static Service service = null;
|
||||
public static Connection connection = null;
|
||||
|
||||
DBus.Connection c;
|
||||
public static int Main(string [] args)
|
||||
{
|
||||
TestServer testServer = new TestServer();
|
||||
Thread serverThread = new Thread(new ThreadStart(testServer.StartServer));
|
||||
serverThread.Start();
|
||||
|
||||
// c = new DBus.Connection ("unix:path=/tmp/foobar");
|
||||
connection = Bus.GetSessionBus();
|
||||
service = Service.Get(connection, "org.freedesktop.Test");
|
||||
|
||||
try {
|
||||
c = DBus.Connection.GetBus (DBus.Connection.BusType.Session);
|
||||
}
|
||||
catch (DBus.Exception e) {
|
||||
Console.Error.WriteLine ("Failed to open connection: {0}",
|
||||
e.Message);
|
||||
return;
|
||||
}
|
||||
TestObject testObject = (TestObject) service.GetObject(typeof(TestObject), "/org/freedesktop/Test/TestObject");
|
||||
|
||||
DBus.Message m = new DBus.Message ("org.freedesktop.Foo",
|
||||
"org.freedesktop.DBus.Broadcast");
|
||||
System.Console.WriteLine(testObject.Test1("Hello"));
|
||||
|
||||
c.Send (m);
|
||||
c.Flush ();
|
||||
//RunTests(testObject);
|
||||
|
||||
IntPtr loop = g_main_loop_new (IntPtr.Zero, false);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
19
mono/example/EchoClient.cs
Normal file
19
mono/example/EchoClient.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
23
mono/example/EchoServer.cs
Normal file
23
mono/example/EchoServer.cs
Normal 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
16
mono/example/Echoer.cs
Normal 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
19
mono/example/Makefile.am
Normal 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
|
||||
|
||||
Loading…
Add table
Reference in a new issue