diff options
author | Havoc Pennington <hp@redhat.com> | 2003-06-22 22:59:31 +0000 |
---|---|---|
committer | Havoc Pennington <hp@redhat.com> | 2003-06-22 22:59:31 +0000 |
commit | 1cc184b4a849619b56bed2be0e752fbc0fb75a29 (patch) | |
tree | 867409e28e08152147e095606e487793873dd51e /mono/Connection.cs | |
parent | 958805418359aca169cd363a4a3279f0fdab753c (diff) |
2003-06-22 Havoc Pennington <hp@pobox.com>
* mono/Connection.cs, mono/DBus.cs, mono/Error.cs:
Start wrapping more stuff.
Diffstat (limited to 'mono/Connection.cs')
-rw-r--r-- | mono/Connection.cs | 123 |
1 files changed, 123 insertions, 0 deletions
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); + } +} |