From 1cc184b4a849619b56bed2be0e752fbc0fb75a29 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sun, 22 Jun 2003 22:59:31 +0000 Subject: 2003-06-22 Havoc Pennington * mono/Connection.cs, mono/DBus.cs, mono/Error.cs: Start wrapping more stuff. --- ChangeLog | 5 +++ mono/Connection.cs | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++ mono/DBus.cs | 13 ++++++ mono/Error.cs | 29 +++++++++++++ mono/Makefile.am | 6 +-- mono/Message.cs | 19 +++++---- mono/Test.cs | 3 ++ 7 files changed, 186 insertions(+), 12 deletions(-) create mode 100644 mono/Connection.cs create mode 100644 mono/DBus.cs create mode 100644 mono/Error.cs diff --git a/ChangeLog b/ChangeLog index 7e712582..06deccd2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2003-06-22 Havoc Pennington + + * mono/Connection.cs, mono/DBus.cs, mono/Error.cs: + Start wrapping more stuff. + 2003-06-22 Havoc Pennington * mono/Message.cs: implement Message.Wrap() that ensures we only diff --git a/mono/Connection.cs b/mono/Connection.cs new file mode 100644 index 00000000..f0d34eec --- /dev/null +++ b/mono/Connection.cs @@ -0,0 +1,123 @@ +namespace DBus { + + using System; + using System.Runtime.InteropServices; + using System.Diagnostics; + + public class Connection { + + 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) 0) { + dbus_connection_unref (raw); + } else { + Exception e = new Exception (ref error); + error.Free (); + throw e; + } + } + + public static Connection Wrap (IntPtr ptr) { + IntPtr gch_ptr; + + gch_ptr = dbus_connection_get_data (ptr, wrapper_slot); + if (gch_ptr != (IntPtr) 0) { + return (DBus.Connection) ((GCHandle)gch_ptr).Target; + } else { + return new Connection (ptr); + } + } + + // surely there's a convention for this pattern with the property + // and the real member + IntPtr raw_; + IntPtr raw { + get { + return raw_; + } + set { + if (value == raw_) + return; + + if (raw_ != (IntPtr) 0) { + IntPtr gch_ptr; + + gch_ptr = dbus_connection_get_data (raw_, + wrapper_slot); + Debug.Assert (gch_ptr != (IntPtr) 0); + + dbus_connection_set_data (raw_, wrapper_slot, + (IntPtr) 0, (IntPtr) 0); + + ((GCHandle) gch_ptr).Free (); + + dbus_connection_unref (raw_); + } + + raw_ = value; + + if (raw_ != (IntPtr) 0) { + 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) 0); + } + } + } + + ~Connection () { + raw = (IntPtr) 0; // free the native object + } + + Connection (IntPtr r) { + raw = r; + } + + // static constructor runs before any methods + static Connection () { + Debug.Assert (wrapper_slot == -1); + + if (!dbus_connection_allocate_data_slot (ref wrapper_slot)) + throw new OutOfMemoryException (); + + Debug.Assert (wrapper_slot >= 0); + } + + // slot used to store the C# object on the C object + static int wrapper_slot = -1; + + [DllImport (DBus.Internals.Libname, EntryPoint="dbus_connection_open")] + private extern static IntPtr dbus_connection_open (string address, + ref Error error); + + [DllImport (DBus.Internals.Libname, EntryPoint="dbus_connection_unref")] + private extern static void dbus_connection_unref (IntPtr ptr); + + [DllImport (DBus.Internals.Libname, EntryPoint="dbus_connection_ref")] + private extern static void dbus_connection_ref (IntPtr ptr); + + [DllImport (DBus.Internals.Libname, EntryPoint="dbus_connection_allocate_data_slot")] + private extern static bool dbus_connection_allocate_data_slot (ref int slot); + + [DllImport (DBus.Internals.Libname, EntryPoint="dbus_connection_free_data_slot")] + private extern static void dbus_connection_free_data_slot (ref int slot); + + [DllImport (DBus.Internals.Libname, 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.Libname, EntryPoint="dbus_connection_get_data")] + private extern static IntPtr dbus_connection_get_data (IntPtr ptr, + int slot); + } +} diff --git a/mono/DBus.cs b/mono/DBus.cs new file mode 100644 index 00000000..1032792a --- /dev/null +++ b/mono/DBus.cs @@ -0,0 +1,13 @@ +namespace DBus { + + using System; + + public class Exception : ApplicationException { + internal Exception (ref Error error) + : base (Runtime.InteropServices.Marshal.PtrToStringAnsi (error.message)) { } + } + + public class Internals { + public const string Libname = "libdbus-1.so.0"; + } +} diff --git a/mono/Error.cs b/mono/Error.cs new file mode 100644 index 00000000..95c0193b --- /dev/null +++ b/mono/Error.cs @@ -0,0 +1,29 @@ +namespace DBus { + + using System; + using System.Runtime.InteropServices; + + // FIXME add code to verify that size of DBus.Error + // matches the C code. + + [StructLayout (LayoutKind.Sequential)] + internal struct Error { + internal IntPtr name; + internal IntPtr message; + private int dummies; + private IntPtr padding1; + + internal void Init () { + dbus_error_init (ref this); + } + + internal void Free () { + dbus_error_free (ref this); + } + + [DllImport (DBus.Internals.Libname, EntryPoint="dbus_error_init")] + private extern static void dbus_error_init (ref Error error); + [DllImport (DBus.Internals.Libname, EntryPoint="dbus_error_free")] + private extern static void dbus_error_free (ref Error error); + } +} diff --git a/mono/Makefile.am b/mono/Makefile.am index d81bcc28..efd61b4b 100644 --- a/mono/Makefile.am +++ b/mono/Makefile.am @@ -3,16 +3,16 @@ DESTDIR= DLLS=dbus-sharp.dll NOINST_EXES=test-dbus-sharp -DBUS_SHARP_FILES=Message.cs +DBUS_SHARP_FILES= DBus.cs Message.cs Connection.cs Error.cs TEST_DBUS_SHARP_FILES=Test.cs all: $(DLLS) $(NOINST_EXES) dbus-sharp.dll: $(DBUS_SHARP_FILES) - $(MCS) $(MCSFLAGS) --unsafe --target library -o dbus-sharp.dll --recurse '$(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 --recurse '$(TEST_DBUS_SHARP_FILES)' + $(MCS) $(MCSFLAGS) --unsafe --target exe -L . -r dbus-sharp.dll -o test-dbus-sharp $(TEST_DBUS_SHARP_FILES) clean: rm -f $(DLLS) $(NOINST_EXES) diff --git a/mono/Message.cs b/mono/Message.cs index 0e41c9ec..a6d3c092 100644 --- a/mono/Message.cs +++ b/mono/Message.cs @@ -10,6 +10,8 @@ namespace DBus { string dest_service) { // the assignment bumps the refcount raw = dbus_message_new (name, dest_service); + if (raw == (IntPtr) 0) + throw new OutOfMemoryException (); dbus_message_unref (raw); } @@ -92,34 +94,33 @@ namespace DBus { // slot used to store the C# object on the C object static int wrapper_slot = -1; - const string libname = "libdbus-1.so.0"; - [DllImport (libname, EntryPoint="dbus_message_new")] + [DllImport (DBus.Internals.Libname, EntryPoint="dbus_message_new")] private extern static IntPtr dbus_message_new (string name, string dest_service); - [DllImport (libname, EntryPoint="dbus_message_unref")] + [DllImport (DBus.Internals.Libname, EntryPoint="dbus_message_unref")] private extern static void dbus_message_unref (IntPtr ptr); - [DllImport (libname, EntryPoint="dbus_message_ref")] + [DllImport (DBus.Internals.Libname, EntryPoint="dbus_message_ref")] private extern static void dbus_message_ref (IntPtr ptr); - [DllImport (libname, EntryPoint="dbus_message_get_name")] + [DllImport (DBus.Internals.Libname, EntryPoint="dbus_message_get_name")] private extern static string dbus_message_get_name (IntPtr ptr); - [DllImport (libname, EntryPoint="dbus_message_allocate_data_slot")] + [DllImport (DBus.Internals.Libname, EntryPoint="dbus_message_allocate_data_slot")] private extern static bool dbus_message_allocate_data_slot (ref int slot); - [DllImport (libname, EntryPoint="dbus_message_free_data_slot")] + [DllImport (DBus.Internals.Libname, EntryPoint="dbus_message_free_data_slot")] private extern static void dbus_message_free_data_slot (ref int slot); - [DllImport (libname, EntryPoint="dbus_message_set_data")] + [DllImport (DBus.Internals.Libname, EntryPoint="dbus_message_set_data")] private extern static bool dbus_message_set_data (IntPtr ptr, int slot, IntPtr data, IntPtr free_data_func); - [DllImport (libname, EntryPoint="dbus_message_get_data")] + [DllImport (DBus.Internals.Libname, EntryPoint="dbus_message_get_data")] private extern static IntPtr dbus_message_get_data (IntPtr ptr, int slot); } diff --git a/mono/Test.cs b/mono/Test.cs index ffe7d0a6..e07504d7 100644 --- a/mono/Test.cs +++ b/mono/Test.cs @@ -4,6 +4,9 @@ using System; class Test { static void Main() { DBus.Message m; + DBus.Connection c; + + c = new DBus.Connection ("unix:path=/tmp/foobar"); m = new DBus.Message ("org.freedesktop.Foo", null); -- cgit