Commit c9160377 authored by Owen Fraser-Green's avatar Owen Fraser-Green

First checkin of the Mono bindings.

parent 2195cf0d
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}
......
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
Name: DBus#
Description: DBus# - D-BUS .NET Bindings
Version: 0.1
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);
}
}
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);
}
}
This diff is collapsed.
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;
}
}
}
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 ();
}
}
namespace DBus
{
using System;
using System.Runtime.InteropServices;
public class DBusException : ApplicationException
{
internal DBusException (Error error) : base (error.Message) {
error.Free();
}
}
}
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);
}
}
<
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);
}