efl_mono: Adding support code for the C# binding
authorLauro Moura <lauromoura@expertisesolutions.com.br>
Fri, 24 Nov 2017 00:49:22 +0000 (21:49 -0300)
committerLauro Moura <lauromoura@expertisesolutions.com.br>
Mon, 4 Dec 2017 18:47:49 +0000 (15:47 -0300)
This is the C# manual code for the binding. Buildsystem integration will
come in a future commit.

31 files changed:
src/bindings/mono/ecore_evas_mono/ecore_evas.cs [new file with mode: 0644]
src/bindings/mono/efl_mono/.gitignore [new file with mode: 0644]
src/bindings/mono/efl_mono/efl_all.cs [new file with mode: 0644]
src/bindings/mono/efl_mono/efl_libs.cs.in [new file with mode: 0644]
src/bindings/mono/efl_mono/efl_libs.csv.in [new file with mode: 0644]
src/bindings/mono/eina_mono/eina_array.cs [new file with mode: 0644]
src/bindings/mono/eina_mono/eina_binbuf.cs [new file with mode: 0644]
src/bindings/mono/eina_mono/eina_common.cs [new file with mode: 0644]
src/bindings/mono/eina_mono/eina_config.cs [new file with mode: 0644]
src/bindings/mono/eina_mono/eina_container_common.cs [new file with mode: 0644]
src/bindings/mono/eina_mono/eina_error.cs [new file with mode: 0644]
src/bindings/mono/eina_mono/eina_hash.cs [new file with mode: 0644]
src/bindings/mono/eina_mono/eina_inarray.cs [new file with mode: 0644]
src/bindings/mono/eina_mono/eina_inlist.cs [new file with mode: 0644]
src/bindings/mono/eina_mono/eina_iterator.cs [new file with mode: 0644]
src/bindings/mono/eina_mono/eina_list.cs [new file with mode: 0644]
src/bindings/mono/eina_mono/eina_log.cs [new file with mode: 0644]
src/bindings/mono/eina_mono/eina_slice.cs [new file with mode: 0644]
src/bindings/mono/eina_mono/eina_stringshare.cs [new file with mode: 0644]
src/bindings/mono/eina_mono/eina_value.cs [new file with mode: 0644]
src/bindings/mono/eldbus_mono/eldbus_common.cs [new file with mode: 0644]
src/bindings/mono/eldbus_mono/eldbus_config.cs [new file with mode: 0644]
src/bindings/mono/eldbus_mono/eldbus_connection.cs [new file with mode: 0644]
src/bindings/mono/eldbus_mono/eldbus_message.cs [new file with mode: 0644]
src/bindings/mono/eldbus_mono/eldbus_object.cs [new file with mode: 0644]
src/bindings/mono/eldbus_mono/eldbus_pending.cs [new file with mode: 0644]
src/bindings/mono/eldbus_mono/eldbus_proxy.cs [new file with mode: 0644]
src/bindings/mono/eldbus_mono/eldbus_service.cs [new file with mode: 0644]
src/bindings/mono/eo_mono/iwrapper.cs [new file with mode: 0644]
src/bindings/mono/eo_mono/object.cs [new file with mode: 0644]
src/bindings/mono/eo_mono/workaround.cs [new file with mode: 0644]

diff --git a/src/bindings/mono/ecore_evas_mono/ecore_evas.cs b/src/bindings/mono/ecore_evas_mono/ecore_evas.cs
new file mode 100644 (file)
index 0000000..a1c8a6d
--- /dev/null
@@ -0,0 +1,37 @@
+
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+public class EcoreEvas
+{
+    [DllImport(efl.Libs.EcoreEvas)] static extern void ecore_evas_init();
+    // [DllImport(efl.Libs.EcoreEvas)] static extern IntPtr ecore_evas_new([MarshalAs(UnmanagedType.LPStr)] String engine_name, int x, int y, int w, int h
+    //                                                               , [MarshalAs(UnmanagedType.LPStr)] String extra_options);
+    [DllImport(efl.Libs.EcoreEvas)] static extern IntPtr ecore_evas_new(IntPtr engine_name, int x, int y, int w, int h
+                                                                  , IntPtr extra_options);
+    [DllImport(efl.Libs.EcoreEvas)] static extern IntPtr ecore_evas_get(IntPtr ecore_evas);
+    [DllImport(efl.Libs.EcoreEvas)] static extern IntPtr ecore_evas_show(IntPtr ecore_evas);
+
+    IntPtr handle;
+    public EcoreEvas()
+    {
+#if WIN32 // Not a native define, we define it in our build system
+        // Ecore_Win32 uses OleInitialize, which requires single thread apartments
+        if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
+            throw new InvalidOperationException("UI Applications require STAThreadAttribute in Main()");
+#endif
+        ecore_evas_init();
+        handle = ecore_evas_new(IntPtr.Zero, 0, 0, 640, 480, IntPtr.Zero);
+        if(handle == IntPtr.Zero)
+            System.Console.WriteLine("Couldn't create a ecore evas");
+        ecore_evas_show(handle);
+    }
+
+    public efl.canvas.Object canvas
+    {
+        get { return new efl.canvas.ObjectConcrete(ecore_evas_get(handle)); }
+    }
+    
+}
+
diff --git a/src/bindings/mono/efl_mono/.gitignore b/src/bindings/mono/efl_mono/.gitignore
new file mode 100644 (file)
index 0000000..cc8a6c3
--- /dev/null
@@ -0,0 +1 @@
+/efl_libs.cs
diff --git a/src/bindings/mono/efl_mono/efl_all.cs b/src/bindings/mono/efl_mono/efl_all.cs
new file mode 100644 (file)
index 0000000..697cdf2
--- /dev/null
@@ -0,0 +1,88 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+using static efl.UnsafeNativeMethods;
+
+namespace efl {
+
+static class UnsafeNativeMethods {
+    [DllImport(efl.Libs.Ecore)] public static extern void ecore_init();
+    [DllImport(efl.Libs.Ecore)] public static extern void ecore_shutdown();
+    [DllImport(efl.Libs.Evas)] public static extern void evas_init();
+    [DllImport(efl.Libs.Evas)] public static extern void evas_shutdown();
+    [DllImport(efl.Libs.Elementary)] public static extern int elm_init(int argc, IntPtr argv);
+    [DllImport(efl.Libs.Elementary)] public static extern void elm_policy_set(int policy, int policy_detail);
+    [DllImport(efl.Libs.Elementary)] public static extern void elm_shutdown();
+    [DllImport(efl.Libs.Elementary)] public static extern void elm_run();
+    [DllImport(efl.Libs.Elementary)] public static extern void elm_exit();
+}
+
+public enum Components {
+    Basic,
+    Ui
+}
+
+public static class All {
+    private static bool InitializedUi = false;
+
+    public static void Init(efl.Components components=Components.Basic) {
+        eina.Config.Init();
+        efl.eo.Config.Init();
+        ecore_init();
+        evas_init();
+        eldbus.Config.Init();
+
+        if (components == Components.Ui) {
+            efl.ui.Config.Init();
+            InitializedUi = true;
+        }
+    }
+
+    /// <summary>Shutdowns all EFL subsystems.</summary>
+    public static void Shutdown() {
+        // Try to cleanup everything before actually shutting down.
+        System.GC.Collect();
+        System.GC.WaitForPendingFinalizers();
+
+        if (InitializedUi)
+            efl.ui.Config.Shutdown();
+        eldbus.Config.Shutdown();
+        evas_shutdown();
+        ecore_shutdown();
+        efl.eo.Config.Shutdown();
+        eina.Config.Shutdown();
+    }
+}
+
+// Placeholder. Will move to elm_config.cs later
+namespace ui {
+
+public static class Config {
+    public static void Init() {
+        // TODO Support elm command line arguments
+#if WIN32 // Not a native define, we define it in our build system
+        // Ecore_Win32 uses OleInitialize, which requires single thread apartments
+        if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
+            throw new InvalidOperationException("UI Applications require STAThreadAttribute in Main()");
+#endif
+        elm_init(0, IntPtr.Zero);
+
+        elm_policy_set((int)elm.Policy.Quit, (int)elm.policy.Quit.Last_window_hidden);
+    }
+    public static void Shutdown() {
+        elm_shutdown();
+    }
+
+    public static void Run() {
+        elm_run();
+    }
+
+    public static void Exit() {
+        elm_exit();
+    }
+}
+
+}
+
+}
diff --git a/src/bindings/mono/efl_mono/efl_libs.cs.in b/src/bindings/mono/efl_mono/efl_libs.cs.in
new file mode 100644 (file)
index 0000000..e1c7dc6
--- /dev/null
@@ -0,0 +1,22 @@
+
+namespace efl {
+
+/// <summary>
+/// Define the name of the libraries to be passed to DllImport statements.
+/// </summary>
+public class Libs {
+    public const string Efl = "@EFL_DL_MONO@";
+    public const string Ecore = "@ECORE_DL_MONO@";
+    public const string Eina = "@EINA_DL_MONO@";
+    public const string Eo = "@EO_DL_MONO@";
+    public const string Evas = "@EVAS_DL_MONO@";
+    public const string Evil = "@EVIL_DL_MONO@";
+    public const string EcoreEvas = "@ECORE_EVAS_DL_MONO@";
+    public const string Edje = "@EDJE_DL_MONO@";
+    public const string Elementary = "@ELEMENTARY_DL_MONO@";
+    public const string Eldbus = "@ELDBUS_DL_MONO@";
+
+    public const string CustomExports = "@CUSTOM_EXPORTS_MONO_DL_MONO@";
+}
+
+}
diff --git a/src/bindings/mono/efl_mono/efl_libs.csv.in b/src/bindings/mono/efl_mono/efl_libs.csv.in
new file mode 100644 (file)
index 0000000..3e356fe
--- /dev/null
@@ -0,0 +1 @@
+@EFL_MONO_LIBRARY_MAP@\r
diff --git a/src/bindings/mono/eina_mono/eina_array.cs b/src/bindings/mono/eina_mono/eina_array.cs
new file mode 100644 (file)
index 0000000..98e43b8
--- /dev/null
@@ -0,0 +1,291 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+using static eina.TraitFunctions;
+using static eina.ArrayNativeFunctions;
+
+namespace eina {
+
+public static class ArrayNativeFunctions
+{
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_array_new(uint step);
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_array_free(IntPtr array);
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_array_flush(IntPtr array);
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_array_remove(IntPtr array, IntPtr keep, IntPtr gdata);
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_array_push(IntPtr array, IntPtr data);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_array_iterator_new(IntPtr array);
+
+    [DllImport(efl.Libs.CustomExports)] public static extern void
+        eina_array_clean_custom_export_mono(IntPtr array);
+    [DllImport(efl.Libs.CustomExports)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_array_push_custom_export_mono(IntPtr array, IntPtr data);
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        eina_array_pop_custom_export_mono(IntPtr array);
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        eina_array_data_get_custom_export_mono(IntPtr array, uint idx);
+    [DllImport(efl.Libs.CustomExports)] public static extern void
+        eina_array_data_set_custom_export_mono(IntPtr array, uint idx, IntPtr data);
+    [DllImport(efl.Libs.CustomExports)] public static extern uint
+        eina_array_count_custom_export_mono(IntPtr array);
+
+    [DllImport(efl.Libs.CustomExports)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_array_foreach_custom_export_mono(IntPtr array, IntPtr cb, IntPtr fdata);
+}
+
+public class Array<T> : IEnumerable<T>, IDisposable
+{
+    public static uint DefaultStep = 32;
+
+    public IntPtr Handle {get;set;} = IntPtr.Zero;
+    public bool Own {get;set;}
+    public bool OwnContent {get;set;}
+
+    public int Length
+    {
+        get { return Count(); }
+    }
+
+
+    private void InitNew(uint step)
+    {
+        Handle = eina_array_new(step);
+        Own = true;
+        OwnContent = true;
+        if (Handle == IntPtr.Zero)
+            throw new SEHException("Could not alloc array");
+    }
+
+    internal bool InternalPush(IntPtr ele)
+    {
+        return eina_array_push_custom_export_mono(Handle, ele);
+    }
+
+    internal IntPtr InternalPop()
+    {
+        return eina_array_pop_custom_export_mono(Handle);
+    }
+
+    internal IntPtr InternalDataGet(int idx)
+    {
+        return eina_array_data_get_custom_export_mono(Handle, (uint)idx); // TODO: Check bounds ???
+    }
+
+    internal void InternalDataSet(int idx, IntPtr ele)
+    {
+        eina_array_data_set_custom_export_mono(Handle, (uint)idx, ele); // TODO: Check bounds ???
+    }
+
+    public Array()
+    {
+        InitNew(DefaultStep);
+    }
+
+    public Array(uint step)
+    {
+        InitNew(step);
+    }
+
+    public Array(IntPtr handle, bool own)
+    {
+        Handle = handle;
+        Own = own;
+        OwnContent = own;
+    }
+
+    public Array(IntPtr handle, bool own, bool ownContent)
+    {
+        Handle = handle;
+        Own = own;
+        OwnContent = ownContent;
+    }
+
+    ~Array()
+    {
+        Dispose(false);
+    }
+
+    protected virtual void Dispose(bool disposing)
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        if (h == IntPtr.Zero)
+            return;
+
+        if (OwnContent)
+        {
+            int len = (int)eina_array_count_custom_export_mono(h);
+            for(int i = 0; i < len; ++i)
+            {
+                NativeFree<T>(eina_array_data_get_custom_export_mono(h, (uint)i));
+            }
+        }
+
+        if (Own)
+            eina_array_free(h);
+    }
+
+    public void Dispose()
+    {
+        Dispose(true);
+        GC.SuppressFinalize(this);
+    }
+
+    public void Free()
+    {
+        Dispose();
+    }
+
+    public IntPtr Release()
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        return h;
+    }
+
+    private void FreeElementsIfOwned()
+    {
+        if (OwnContent)
+        {
+            int len = Length;
+            for(int i = 0; i < len; ++i)
+            {
+                NativeFree<T>(InternalDataGet(i));
+            }
+        }
+    }
+
+    public void Clean()
+    {
+        FreeElementsIfOwned();
+        eina_array_clean_custom_export_mono(Handle);
+    }
+
+    public void Flush()
+    {
+        FreeElementsIfOwned();
+        eina_array_flush(Handle);
+    }
+
+    public int Count()
+    {
+        return (int) eina_array_count_custom_export_mono(Handle);
+    }
+
+    public void SetOwnership(bool ownAll)
+    {
+        Own = ownAll;
+        OwnContent = ownAll;
+    }
+
+    public void SetOwnership(bool own, bool ownContent)
+    {
+        Own = own;
+        OwnContent = ownContent;
+    }
+
+    public bool Push(T val)
+    {
+        IntPtr ele = ManagedToNativeAlloc(val);
+        var r = InternalPush(ele);
+        if (!r)
+            NativeFree<T>(ele);
+        return r;
+    }
+
+// TODO ???
+//     public void Add(T val)
+//     {
+//         if (!Push(val))
+//           throw;
+//     }
+
+    public T Pop()
+    {
+        IntPtr ele = InternalPop();
+        var r = NativeToManaged<T>(ele);
+        if (OwnContent && ele != IntPtr.Zero)
+            NativeFree<T>(ele);
+        return r;
+    }
+
+    public T DataGet(int idx)
+    {
+        IntPtr ele = InternalDataGet(idx);
+        return NativeToManaged<T>(ele);
+    }
+
+    public T At(int idx)
+    {
+        return DataGet(idx);
+    }
+
+    public void DataSet(int idx, T val)
+    {
+        IntPtr ele = InternalDataGet(idx); // TODO: check bondaries ??
+        if (OwnContent && ele != IntPtr.Zero)
+            NativeFree<T>(ele);
+        ele = ManagedToNativeAlloc(val);
+        InternalDataSet(idx, ele);
+    }
+
+    public T this[int idx]
+    {
+        get
+        {
+            return DataGet(idx);
+        }
+        set
+        {
+            DataSet(idx, value);
+        }
+    }
+
+    public T[] ToArray()
+    {
+        int len = Length;
+        var managed = new T[len];
+        for(int i = 0; i < len; ++i)
+        {
+            managed[i] = DataGet(i);
+        }
+        return managed;
+    }
+
+    public bool Append(T[] values)
+    {
+        foreach(T v in values)
+            if (!Push(v))
+                return false;
+        return true;
+    }
+
+
+    public eina.Iterator<T> GetIterator()
+    {
+        return new eina.Iterator<T>(eina_array_iterator_new(Handle), true, false);
+    }
+
+    public IEnumerator<T> GetEnumerator()
+    {
+        int len = Length;
+        for(int i = 0; i < len; ++i)
+        {
+            yield return DataGet(i);
+        }
+    }
+
+    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+    {
+        return this.GetEnumerator();
+    }
+}
+
+}
diff --git a/src/bindings/mono/eina_mono/eina_binbuf.cs b/src/bindings/mono/eina_mono/eina_binbuf.cs
new file mode 100644 (file)
index 0000000..dd30ab1
--- /dev/null
@@ -0,0 +1,210 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace eina {
+
+public class Binbuf : IDisposable
+{
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_binbuf_new();
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_binbuf_free(IntPtr buf);
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_binbuf_reset(IntPtr buf);
+    [DllImport(efl.Libs.Eina)] public static extern byte
+        eina_binbuf_append_length(IntPtr buf, byte[] str, UIntPtr length);
+    [DllImport(efl.Libs.Eina)] public static extern byte
+        eina_binbuf_append_slice(IntPtr buf, eina.Slice slice);
+    [DllImport(efl.Libs.Eina)] public static extern byte
+        eina_binbuf_append_buffer(IntPtr buf, IntPtr data);
+    [DllImport(efl.Libs.Eina)] public static extern byte
+        eina_binbuf_append_char(IntPtr buf, byte c);
+    [DllImport(efl.Libs.Eina)] public static extern byte
+        eina_binbuf_insert_length(IntPtr buf, byte[] str, UIntPtr length, UIntPtr pos);
+    [DllImport(efl.Libs.Eina)] public static extern byte
+        eina_binbuf_insert_slice(IntPtr buf, eina.Slice slice, UIntPtr pos);
+    [DllImport(efl.Libs.Eina)] public static extern byte
+        eina_binbuf_insert_char(IntPtr buf, byte c, UIntPtr pos);
+    [DllImport(efl.Libs.Eina)] public static extern byte
+        eina_binbuf_remove(IntPtr buf, UIntPtr start, UIntPtr end);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_binbuf_string_get(IntPtr buf);
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_binbuf_string_free(IntPtr buf);
+    [DllImport(efl.Libs.Eina)] public static extern UIntPtr
+        eina_binbuf_length_get(IntPtr buf);
+    [DllImport(efl.Libs.Eina)] public static extern eina.Slice
+        eina_binbuf_slice_get(IntPtr buf);
+
+    public IntPtr Handle {get;set;} = IntPtr.Zero;
+    public bool Own {get;set;}
+
+    public int Length
+    {
+        get { return (int) GetLength(); }
+    }
+
+    private void InitNew()
+    {
+        Handle = eina_binbuf_new();
+        Own = true;
+        if (Handle == IntPtr.Zero)
+            throw new SEHException("Could not alloc binbuf");
+    }
+
+    public Binbuf()
+    {
+        InitNew();
+    }
+
+    public Binbuf(byte[] str, uint? length = null)
+    {
+        InitNew();
+
+        if (str != null)
+        {
+            if (!Append(str, (length != null ? length.Value : (uint)(str.Length))))
+            {
+                Dispose();
+                throw new SEHException("Could not append on binbuf");
+            }
+        }
+    }
+
+    public Binbuf(Binbuf bb)
+    {
+        InitNew();
+
+        if (bb != null)
+        {
+            Append(bb);
+        }
+    }
+
+    public Binbuf(IntPtr handle, bool own)
+    {
+        Handle = handle;
+        Own = own;
+    }
+
+    ~Binbuf()
+    {
+        Dispose(false);
+    }
+
+    protected virtual void Dispose(bool disposing)
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        if (Own && h != IntPtr.Zero) {
+            eina_binbuf_free(Handle);
+        }
+    }
+
+    public void Dispose()
+    {
+        Dispose(true);
+        GC.SuppressFinalize(this);
+    }
+
+    public void Free()
+    {
+        Dispose();
+    }
+
+    public IntPtr Release()
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        return h;
+    }
+
+    public void Reset()
+    {
+        eina_binbuf_reset(Handle);
+    }
+
+    public bool Append(byte[] str)
+    {
+        return 0 != eina_binbuf_append_length(Handle, str, (UIntPtr)(str.Length));
+    }
+
+    public bool Append(byte[] str, uint length)
+    {
+        return 0 != eina_binbuf_append_length(Handle, str, (UIntPtr)length);
+    }
+
+    public bool Append(Binbuf bb)
+    {
+        return 0 != eina_binbuf_append_buffer(Handle, bb.Handle);
+    }
+
+    public bool Append(byte c)
+    {
+        return 0 != eina_binbuf_append_char(Handle, c);
+    }
+
+    public bool Append(eina.Slice slice)
+    {
+        return 0 != eina_binbuf_append_slice(Handle, slice);
+    }
+
+    public bool Insert(byte[] str, uint pos)
+    {
+        return 0 != eina_binbuf_insert_length(Handle, str, (UIntPtr)(str.Length), (UIntPtr)pos);
+    }
+
+    public bool Insert(byte[] str, uint length, uint pos)
+    {
+        return 0 != eina_binbuf_insert_length(Handle, str, (UIntPtr)length, (UIntPtr)pos);
+    }
+
+    public bool Insert(byte c, uint pos)
+    {
+        return 0 != eina_binbuf_insert_char(Handle, c, (UIntPtr)pos);
+    }
+
+    public bool Insert(eina.Slice slice, uint pos)
+    {
+        return 0 != eina_binbuf_insert_slice(Handle, slice, (UIntPtr)pos);
+    }
+
+    public bool Remove(uint start, uint end)
+    {
+        return 0 != eina_binbuf_remove(Handle, (UIntPtr)start, (UIntPtr)end);
+    }
+
+    public byte[] GetBytes()
+    {
+        var ptr = eina_binbuf_string_get(Handle);
+        if (ptr == IntPtr.Zero)
+            return null;
+
+        var size = (int)(this.GetLength());
+        byte[] mArray = new byte[size];
+        Marshal.Copy(ptr, mArray, 0, size);
+        return mArray;
+    }
+
+    public IntPtr GetStringNative()
+    {
+        return eina_binbuf_string_get(Handle);
+    }
+
+    public void FreeString()
+    {
+        eina_binbuf_string_free(Handle);
+    }
+
+    public UIntPtr GetLength()
+    {
+        return eina_binbuf_length_get(Handle);
+    }
+
+    eina.Slice GetSlice()
+    {
+        return eina_binbuf_slice_get(Handle);
+    }
+}
+
+}
diff --git a/src/bindings/mono/eina_mono/eina_common.cs b/src/bindings/mono/eina_mono/eina_common.cs
new file mode 100644 (file)
index 0000000..05a5625
--- /dev/null
@@ -0,0 +1,132 @@
+using System;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace eina
+{
+namespace Callbacks
+{
+
+public delegate int Eina_Compare_Cb(IntPtr data1, IntPtr data2);
+public delegate void Eina_Free_Cb(IntPtr data);
+
+}
+
+public static class NativeCustomExportFunctions
+{
+    [DllImport(efl.Libs.CustomExports)] public static extern void
+        efl_mono_native_free(IntPtr ptr);
+    [DllImport(efl.Libs.CustomExports)] public static extern void
+        efl_mono_native_free_ref(IntPtr ptr);
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        efl_mono_native_alloc(uint count);
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        efl_mono_native_alloc_copy(IntPtr val, uint size);
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        efl_mono_native_strdup(string str);
+
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        efl_mono_native_ptr_compare_addr_get();
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        efl_mono_native_str_compare_addr_get();
+
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        efl_mono_native_free_addr_get();
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        efl_mono_native_efl_unref_addr_get();
+}
+
+/// <summary>Wrapper around native memory DllImport'd functions</summary>
+public static class MemoryNative {
+    public static void Free(IntPtr ptr)
+    {
+        NativeCustomExportFunctions.efl_mono_native_free(ptr);
+    }
+
+    public static void FreeRef(IntPtr ptr)
+    {
+        NativeCustomExportFunctions.efl_mono_native_free_ref(ptr);
+    }
+
+    // This public api uses int as Marshal.SizeOf return an int instead of uint.
+    public static IntPtr Alloc(int count)
+    {
+        return NativeCustomExportFunctions.efl_mono_native_alloc(Convert.ToUInt32(count));
+    }
+
+    public static IntPtr AllocCopy(IntPtr ptr, int count)
+    {
+        return NativeCustomExportFunctions.efl_mono_native_alloc_copy(ptr, Convert.ToUInt32(count));
+    }
+
+    public static IntPtr StrDup(string str)
+    {
+        return NativeCustomExportFunctions.efl_mono_native_strdup(str);
+    }
+
+    // IntPtr's for some native functions
+    public static IntPtr PtrCompareFuncPtrGet()
+    {
+        return NativeCustomExportFunctions.efl_mono_native_ptr_compare_addr_get();
+    }
+
+    public static IntPtr StrCompareFuncPtrGet()
+    {
+        return NativeCustomExportFunctions.efl_mono_native_str_compare_addr_get();
+    }
+
+    public static IntPtr FreeFuncPtrGet()
+    {
+        return NativeCustomExportFunctions.efl_mono_native_free_addr_get();
+    }
+
+    public static IntPtr EflUnrefFuncPtrGet()
+    {
+        return NativeCustomExportFunctions.efl_mono_native_efl_unref_addr_get();
+    }
+}
+
+public static class StringConversion
+{
+    public static IntPtr ManagedStringToNativeUtf8Alloc(string managedString)
+    {
+        if (managedString == null)
+            return IntPtr.Zero;
+
+        byte[] strbuf = Encoding.UTF8.GetBytes(managedString);
+        IntPtr native = MemoryNative.Alloc(strbuf.Length + 1);
+        Marshal.Copy(strbuf, 0, native, strbuf.Length);
+        Marshal.WriteByte(native + strbuf.Length, 0); // write the terminating null
+        return native;
+    }
+
+    public static string NativeUtf8ToManagedString(IntPtr pNativeData)
+    {
+        if (pNativeData == IntPtr.Zero)
+            return null;
+
+        int len = 0;
+        while (Marshal.ReadByte(pNativeData, len) != 0)
+            ++len;
+
+        byte[] strbuf = new byte[len];
+        Marshal.Copy(pNativeData, strbuf, 0, strbuf.Length);
+        return Encoding.UTF8.GetString(strbuf);
+    }
+}
+
+public struct Unicode {
+    private uint val;
+
+    public static implicit operator Unicode(uint x)
+    {
+        return new Unicode{val=x};
+    }
+    public static implicit operator uint(Unicode x)
+    {
+        return x.val;
+    }
+}
+
+
+}
diff --git a/src/bindings/mono/eina_mono/eina_config.cs b/src/bindings/mono/eina_mono/eina_config.cs
new file mode 100644 (file)
index 0000000..c33dd06
--- /dev/null
@@ -0,0 +1,62 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace eina {
+
+public class Config {
+    [DllImport(efl.Libs.Eina)] private static extern int eina_init();
+    [DllImport(efl.Libs.Eina)] private static extern int eina_shutdown();
+
+    public static void Init() {
+        if (eina_init() == 0)
+            throw (new efl.EflException("Failed to initialize Eina"));
+
+        // Initialize the submodules here
+        eina.Log.Init();
+        eina.Error.Init();
+    }
+
+    public static int Shutdown() {
+        return eina_shutdown();
+    }
+
+}
+
+/// <summary>
+/// Wrapper class for pointers that need some cleanup afterwards
+/// like strings.
+/// </summary>
+public class DisposableIntPtr : IDisposable {
+
+    public IntPtr Handle { get; set; }
+    private bool ShouldFree;
+    private bool Disposed;
+
+    /// <summary>Wraps a new ptr what will be freed based on the
+    /// value of shouldFree</summary>
+    public DisposableIntPtr(IntPtr ptr, bool shouldFree=false)
+    {
+        Handle = ptr;
+        ShouldFree = shouldFree;
+    }
+
+    public void Dispose()
+    {
+        Dispose(true);
+        GC.SuppressFinalize(this);
+    }
+
+    protected virtual void Dispose(bool disposing)
+    {
+        if (!Disposed && ShouldFree) {
+            MemoryNative.Free(this.Handle);
+        }
+        Disposed = true;
+    }
+
+    ~DisposableIntPtr()
+    {
+        Dispose(false);
+    }
+}
+}
diff --git a/src/bindings/mono/eina_mono/eina_container_common.cs b/src/bindings/mono/eina_mono/eina_container_common.cs
new file mode 100644 (file)
index 0000000..6cdafdc
--- /dev/null
@@ -0,0 +1,683 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+using eina.Callbacks;
+using static eina.HashNativeFunctions;
+using static eina.InarrayNativeFunctions;
+using static eina.InlistNativeFunctions;
+using static eina.NativeCustomExportFunctions;
+using static eina.ContainerCommonData;
+
+namespace eina {
+
+public enum ElementType { NumericType, StringType, ObjectType };
+
+public static class ContainerCommonData
+{
+    public static IBaseElementTraits<IntPtr> intPtrTraits = null;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct ConvertWrapper<T>
+{
+    public T Val {get;set;}
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct InlistMem
+{
+    public IntPtr next {get;set;}
+    public IntPtr prev {get;set;}
+    public IntPtr last {get;set;}
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct InlistNode<T>
+{
+    public InlistMem __in_list {get;set;}
+    public T Val {get;set;}
+}
+
+
+public interface IBaseElementTraits<T>
+{
+    IntPtr ManagedToNativeAlloc(T man);
+    IntPtr ManagedToNativeAllocRef(T man, bool refs);
+    IntPtr ManagedToNativeAllocInlistNode(T man);
+    IntPtr ManagedToNativeAllocInplace(T man);
+    void NativeFree(IntPtr nat);
+    void NativeFreeRef(IntPtr nat, bool unrefs);
+    void NativeFreeInlistNodeElement(IntPtr nat);
+    void NativeFreeInlistNode(IntPtr nat, bool freeElement);
+    void NativeFreeInplace(IntPtr nat);
+    void ResidueFreeInplace(IntPtr nat);
+    T NativeToManaged(IntPtr nat);
+    T NativeToManagedRef(IntPtr nat);
+    T NativeToManagedInlistNode(IntPtr nat);
+    T NativeToManagedInplace(IntPtr nat);
+    IntPtr EinaCompareCb();
+    IntPtr EinaFreeCb();
+    IntPtr EinaHashNew();
+    IntPtr EinaInarrayNew(uint step);
+    IntPtr EinaHashIteratorKeyNew(IntPtr hash);
+}
+
+public class StringElementTraits<T> : IBaseElementTraits<T>
+{
+
+    public StringElementTraits()
+    {
+        if (intPtrTraits == null)
+            intPtrTraits = TraitFunctions.GetTypeTraits<IntPtr>();
+    }
+
+    public IntPtr ManagedToNativeAlloc(T man)
+    {
+        return MemoryNative.StrDup((string)(object)man);
+    }
+
+    public IntPtr ManagedToNativeAllocRef(T man, bool refs)
+    {
+        // Keep alloc on C# ?
+        return ManagedToNativeAlloc(man);
+    }
+
+    public IntPtr ManagedToNativeAllocInlistNode(T man)
+    {
+        var node = new InlistNode<IntPtr>();
+        node.Val = ManagedToNativeAlloc(man);
+        GCHandle pinnedData = GCHandle.Alloc(node, GCHandleType.Pinned);
+        IntPtr ptr = pinnedData.AddrOfPinnedObject();
+        IntPtr nat = MemoryNative.AllocCopy(ptr, Marshal.SizeOf<InlistNode<IntPtr> >());
+        pinnedData.Free();
+        return nat;
+    }
+
+    public IntPtr ManagedToNativeAllocInplace(T man)
+    {
+        return intPtrTraits.ManagedToNativeAlloc(ManagedToNativeAlloc(man));
+    }
+
+    public void NativeFree(IntPtr nat)
+    {
+        if (nat != IntPtr.Zero)
+            MemoryNative.Free(nat);
+    }
+
+    public void NativeFreeRef(IntPtr nat, bool unrefs)
+    {
+        NativeFree(nat);
+    }
+
+    public void NativeFreeInlistNodeElement(IntPtr nat)
+    {
+        if (nat == IntPtr.Zero)
+            return;
+        var node = Marshal.PtrToStructure< InlistNode<IntPtr> >(nat);
+        NativeFree(node.Val);
+    }
+
+    public void NativeFreeInlistNode(IntPtr nat, bool freeElement)
+    {
+        if (nat == IntPtr.Zero)
+            return;
+        if (freeElement)
+            NativeFreeInlistNodeElement(nat);
+        MemoryNative.Free(nat);
+    }
+
+    public void NativeFreeInplace(IntPtr nat)
+    {
+        MemoryNative.FreeRef(nat);
+    }
+
+    public void ResidueFreeInplace(IntPtr nat)
+    {
+        intPtrTraits.NativeFree(nat);
+    }
+
+    public T NativeToManaged(IntPtr nat)
+    {
+        if (nat == IntPtr.Zero)
+            return default(T);
+        return (T)(object)StringConversion.NativeUtf8ToManagedString(nat);
+    }
+
+    public T NativeToManagedRef(IntPtr nat)
+    {
+        return NativeToManaged(nat);
+    }
+
+    public T NativeToManagedInlistNode(IntPtr nat)
+    {
+        if (nat == IntPtr.Zero)
+        {
+            eina.Log.Error("Null pointer for Inlist node.");
+            return default(T);
+        }
+        var w = Marshal.PtrToStructure< InlistNode<IntPtr> >(nat);
+        return NativeToManaged(w.Val);
+    }
+
+    public T NativeToManagedInplace(IntPtr nat)
+    {
+        if (nat == IntPtr.Zero)
+            return default(T);
+        return NativeToManaged(intPtrTraits.NativeToManaged(nat));
+    }
+
+    public IntPtr EinaCompareCb()
+    {
+        return MemoryNative.StrCompareFuncPtrGet();
+    }
+
+    public IntPtr EinaFreeCb()
+    {
+        return MemoryNative.FreeFuncPtrGet();
+    }
+
+    public IntPtr EinaHashNew()
+    {
+        return eina_hash_string_superfast_new(IntPtr.Zero);
+    }
+
+    public IntPtr EinaInarrayNew(uint step)
+    {
+        return eina_inarray_new((uint)Marshal.SizeOf<IntPtr>(), step);
+    }
+
+    public IntPtr EinaHashIteratorKeyNew(IntPtr hash)
+    {
+        return eina_hash_iterator_key_new(hash);
+    }
+}
+
+public class EflObjectElementTraits<T> : IBaseElementTraits<T>
+{
+    private System.Type concreteType = null;
+
+    public EflObjectElementTraits(System.Type concrete)
+    {
+        if (intPtrTraits == null)
+            intPtrTraits = TraitFunctions.GetTypeTraits<IntPtr>();
+
+        concreteType = concrete;
+    }
+
+    public IntPtr ManagedToNativeAlloc(T man)
+    {
+        IntPtr h = ((efl.eo.IWrapper)man).raw_handle;
+        if (h == IntPtr.Zero)
+            return h;
+        return efl.eo.Globals.efl_ref(h);
+    }
+
+    public IntPtr ManagedToNativeAllocRef(T man, bool refs)
+    {
+        IntPtr h = refs ? ManagedToNativeAlloc(man) : ((efl.eo.IWrapper)man).raw_handle;
+        return intPtrTraits.ManagedToNativeAlloc(h);
+    }
+
+    public IntPtr ManagedToNativeAllocInlistNode(T man)
+    {
+        var node = new InlistNode<IntPtr>();
+        node.Val = ManagedToNativeAlloc(man);
+        GCHandle pinnedData = GCHandle.Alloc(node, GCHandleType.Pinned);
+        IntPtr ptr = pinnedData.AddrOfPinnedObject();
+        IntPtr nat = MemoryNative.AllocCopy(ptr, Marshal.SizeOf<InlistNode<IntPtr> >());
+        pinnedData.Free();
+        return nat;
+    }
+
+    public IntPtr ManagedToNativeAllocInplace(T man)
+    {
+        return intPtrTraits.ManagedToNativeAlloc(ManagedToNativeAlloc(man));
+    }
+
+    public void NativeFree(IntPtr nat)
+    {
+        if (nat != IntPtr.Zero)
+            efl.eo.Globals.efl_unref(nat);
+    }
+
+    public void NativeFreeRef(IntPtr nat, bool unrefs)
+    {
+        if (unrefs)
+            NativeFree(intPtrTraits.NativeToManaged(nat));
+        intPtrTraits.NativeFree(nat);
+    }
+
+    public void NativeFreeInlistNodeElement(IntPtr nat)
+    {
+        if (nat == IntPtr.Zero)
+            return;
+        var node = Marshal.PtrToStructure< InlistNode<IntPtr> >(nat);
+        NativeFree(node.Val);
+    }
+
+    public void NativeFreeInlistNode(IntPtr nat, bool freeElement)
+    {
+        if (nat == IntPtr.Zero)
+            return;
+        if (freeElement)
+            NativeFreeInlistNodeElement(nat);
+        MemoryNative.Free(nat);
+    }
+
+    public void NativeFreeInplace(IntPtr nat)
+    {
+        NativeFree(intPtrTraits.NativeToManaged(nat));
+    }
+
+    public void ResidueFreeInplace(IntPtr nat)
+    {
+        intPtrTraits.NativeFree(nat);
+    }
+
+    public T NativeToManaged(IntPtr nat)
+    {
+        if (nat == IntPtr.Zero)
+            return default(T);
+        return (T) Activator.CreateInstance(concreteType, efl.eo.Globals.efl_ref(nat));
+    }
+
+    public T NativeToManagedRef(IntPtr nat)
+    {
+        if (nat == IntPtr.Zero)
+            return default(T);
+        return NativeToManaged(intPtrTraits.NativeToManaged(nat));
+    }
+
+    public T NativeToManagedInlistNode(IntPtr nat)
+    {
+        if (nat == IntPtr.Zero)
+        {
+            eina.Log.Error("Null pointer for Inlist node.");
+            return default(T);
+        }
+        var w = Marshal.PtrToStructure< InlistNode<IntPtr> >(nat);
+        return NativeToManaged(w.Val);
+    }
+
+    public T NativeToManagedInplace(IntPtr nat)
+    {
+        if (nat == IntPtr.Zero)
+            return default(T);
+        return NativeToManaged(intPtrTraits.NativeToManaged(nat));
+    }
+
+    public IntPtr EinaCompareCb()
+    {
+        return MemoryNative.PtrCompareFuncPtrGet();
+    }
+
+    public IntPtr EinaFreeCb()
+    {
+        return MemoryNative.EflUnrefFuncPtrGet();
+    }
+
+    public IntPtr EinaHashNew()
+    {
+        return eina_hash_pointer_new(IntPtr.Zero);
+    }
+
+    public IntPtr EinaInarrayNew(uint step)
+    {
+        return eina_inarray_new((uint)Marshal.SizeOf<IntPtr>(), step);
+    }
+
+    public IntPtr EinaHashIteratorKeyNew(IntPtr hash)
+    {
+        return eina_hash_iterator_ptr_key_wrapper_new_custom_export_mono(hash);
+    }
+}
+
+public abstract class PrimitiveElementTraits<T>
+{
+    private Eina_Compare_Cb dlgt = null;
+
+    public IntPtr ManagedToNativeAlloc(T man)
+    {
+        GCHandle pinnedData = GCHandle.Alloc(man, GCHandleType.Pinned);
+        IntPtr ptr = pinnedData.AddrOfPinnedObject();
+        IntPtr nat = MemoryNative.AllocCopy(ptr, Marshal.SizeOf<T>());
+        pinnedData.Free();
+        return nat;
+    }
+
+    public IntPtr ManagedToNativeAllocInlistNode(T man)
+    {
+        var node = new InlistNode<T>();
+        node.Val = man;
+        GCHandle pinnedData = GCHandle.Alloc(node, GCHandleType.Pinned);
+        IntPtr ptr = pinnedData.AddrOfPinnedObject();
+        IntPtr nat = MemoryNative.AllocCopy(ptr, Marshal.SizeOf< InlistNode<T> >());
+        pinnedData.Free();
+        return nat;
+    }
+
+    public IntPtr ManagedToNativeAllocInplace(T man)
+    {
+        return ManagedToNativeAlloc(man);
+    }
+
+    public void NativeFree(IntPtr nat)
+    {
+        MemoryNative.Free(nat);
+    }
+
+    public void NativeFreeInlistNodeElement(IntPtr nat)
+    {
+        // Do nothing
+    }
+
+    public void NativeFreeInlistNode(IntPtr nat, bool freeElement)
+    {
+        MemoryNative.Free(nat);
+    }
+
+    public void NativeFreeInplace(IntPtr nat)
+    {
+        // Do nothing
+    }
+
+    public void ResidueFreeInplace(IntPtr nat)
+    {
+        NativeFree(nat);
+    }
+
+    public T NativeToManaged(IntPtr nat)
+    {
+        if (nat == IntPtr.Zero)
+        {
+            eina.Log.Error("Null pointer on primitive/struct container.");
+            return default(T);
+        }
+        var w = Marshal.PtrToStructure<eina.ConvertWrapper<T> >(nat);
+        return w.Val;
+    }
+
+    public T NativeToManagedRef(IntPtr nat)
+    {
+        return NativeToManaged(nat);
+    }
+
+    public T NativeToManagedInlistNode(IntPtr nat)
+    {
+        if (nat == IntPtr.Zero)
+        {
+            eina.Log.Error("Null pointer for Inlist node.");
+            return default(T);
+        }
+        var w = Marshal.PtrToStructure< InlistNode<T> >(nat);
+        return w.Val;
+    }
+
+    public T NativeToManagedInplace(IntPtr nat)
+    {
+        return NativeToManaged(nat);
+    }
+
+    private int PrimitiveCompareCb(IntPtr ptr1, IntPtr ptr2)
+    {
+        var m1 = (IComparable) NativeToManaged(ptr1);
+        var m2 = NativeToManaged(ptr2);
+        return m1.CompareTo(m2);
+    }
+
+    public IntPtr EinaCompareCb()
+    {
+        if (dlgt == null)
+            dlgt = new Eina_Compare_Cb(PrimitiveCompareCb);
+        return Marshal.GetFunctionPointerForDelegate(dlgt);
+    }
+
+    public IntPtr EinaFreeCb()
+    {
+        return MemoryNative.FreeFuncPtrGet();
+    }
+
+    public IntPtr EinaInarrayNew(uint step)
+    {
+        return eina_inarray_new((uint)Marshal.SizeOf<T>(), step);
+    }
+
+    public IntPtr EinaHashIteratorKeyNew(IntPtr hash)
+    {
+        return eina_hash_iterator_key_new(hash);
+    }
+}
+
+public class Primitive32ElementTraits<T> : PrimitiveElementTraits<T>, IBaseElementTraits<T>
+{
+    private static IBaseElementTraits<Int32> int32Traits = null;
+
+    public Primitive32ElementTraits()
+    {
+        if (int32Traits == null)
+            if (typeof(T) == typeof(Int32)) // avoid infinite recursion
+                int32Traits = (IBaseElementTraits<Int32>)this;
+            else
+                int32Traits = TraitFunctions.GetTypeTraits<Int32>();
+    }
+
+    public IntPtr ManagedToNativeAllocRef(T man, bool refs)
+    {
+        return int32Traits.ManagedToNativeAlloc(Convert.ToInt32((object)man));
+    }
+
+    public void NativeFreeRef(IntPtr nat, bool unrefs)
+    {
+        int32Traits.NativeFree(nat);
+    }
+
+    public IntPtr EinaHashNew()
+    {
+        return eina_hash_int32_new(IntPtr.Zero);
+    }
+}
+
+public class Primitive64ElementTraits<T> : PrimitiveElementTraits<T>, IBaseElementTraits<T>
+{
+    private static IBaseElementTraits<Int64> int64Traits = null;
+
+    public Primitive64ElementTraits()
+    {
+        if (int64Traits == null)
+            if (typeof(T) == typeof(Int64)) // avoid infinite recursion
+                int64Traits = (IBaseElementTraits<Int64>)this;
+            else
+                int64Traits = TraitFunctions.GetTypeTraits<Int64>();
+    }
+
+    public IntPtr ManagedToNativeAllocRef(T man, bool refs)
+    {
+        return int64Traits.ManagedToNativeAlloc(Convert.ToInt64((object)man));
+    }
+
+    public void NativeFreeRef(IntPtr nat, bool unrefs)
+    {
+        int64Traits.NativeFree(nat);
+    }
+
+    public IntPtr EinaHashNew()
+    {
+        return eina_hash_int64_new(IntPtr.Zero);
+    }
+}
+
+public static class TraitFunctions
+{
+    public static bool IsEflObject(System.Type type)
+    {
+        return typeof(efl.eo.IWrapper).IsAssignableFrom(type);
+    }
+
+    public static bool IsString(System.Type type)
+    {
+        return type == typeof(string);
+    }
+
+    public static eina.ElementType GetElementTypeCode(System.Type type)
+    {
+        if (IsEflObject(type))
+            return ElementType.ObjectType;
+        else if (IsString(type))
+            return ElementType.StringType;
+        else
+            return ElementType.NumericType;
+    }
+
+    private static IDictionary<System.Type, object> register = new Dictionary<System.Type, object>();
+
+    public static object RegisterTypeTraits<T>()
+    {
+        object traits;
+        var type = typeof(T);
+        if (IsEflObject(type))
+        {
+            System.Type concrete = type;
+            if (!type.Name.EndsWith("Concrete"))
+            {
+                var c = type.Assembly.GetType(type.FullName + "Concrete");
+                if (c != null && type.IsAssignableFrom(c))
+                    concrete = c;
+            }
+            traits = new EflObjectElementTraits<T>(concrete);
+        }
+        else if (IsString(type))
+            traits = new StringElementTraits<T>();
+        else if (type.IsValueType)
+        {
+            if (Marshal.SizeOf<T>() <= 4)
+                traits = new Primitive32ElementTraits<T>();
+            else
+                traits = new Primitive64ElementTraits<T>();
+        }
+        else
+            throw new Exception("No traits registered for this type");
+
+        register[type] = traits;
+        return traits;
+    }
+
+    public static object RegisterTypeTraits<T>(IBaseElementTraits<T> traits)
+    {
+        register[typeof(T)] = traits;
+        return traits;
+    }
+
+    public static IBaseElementTraits<T> GetTypeTraits<T>()
+    {
+        object traits;
+        if (!register.TryGetValue(typeof(T), out traits))
+            traits = RegisterTypeTraits<T>();
+        return (IBaseElementTraits<T>) traits;
+    }
+
+    //                  //
+    // Traits functions //
+    //                  //
+
+    // Convertion functions //
+
+    public static IntPtr ManagedToNativeAlloc<T>(T man)
+    {
+        return GetTypeTraits<T>().ManagedToNativeAlloc(man);
+    }
+
+    public static IntPtr ManagedToNativeAllocRef<T>(T man, bool refs = false)
+    {
+        return GetTypeTraits<T>().ManagedToNativeAllocRef(man, refs);
+    }
+
+    public static IntPtr ManagedToNativeAllocInplace<T>(T man)
+    {
+        return GetTypeTraits<T>().ManagedToNativeAllocInplace(man);
+    }
+
+    public static IntPtr ManagedToNativeAllocInlistNode<T>(T man)
+    {
+        return GetTypeTraits<T>().ManagedToNativeAllocInlistNode(man);
+    }
+
+    public static void NativeFree<T>(IntPtr nat)
+    {
+        GetTypeTraits<T>().NativeFree(nat);
+    }
+
+    public static void NativeFreeRef<T>(IntPtr nat, bool unrefs = false)
+    {
+        GetTypeTraits<T>().NativeFreeRef(nat, unrefs);
+    }
+
+    public static void NativeFreeInlistNodeElement<T>(IntPtr nat)
+    {
+        GetTypeTraits<T>().NativeFreeInlistNodeElement(nat);
+    }
+
+    public static void NativeFreeInlistNode<T>(IntPtr nat, bool freeElement = true)
+    {
+        GetTypeTraits<T>().NativeFreeInlistNode(nat, freeElement);
+    }
+
+    public static void NativeFreeInplace<T>(IntPtr nat)
+    {
+        GetTypeTraits<T>().NativeFreeInplace(nat);
+    }
+
+    public static void ResidueFreeInplace<T>(IntPtr nat)
+    {
+        GetTypeTraits<T>().ResidueFreeInplace(nat);
+    }
+
+    public static T NativeToManaged<T>(IntPtr nat)
+    {
+        return GetTypeTraits<T>().NativeToManaged(nat);
+    }
+
+    public static T NativeToManagedRef<T>(IntPtr nat)
+    {
+        return GetTypeTraits<T>().NativeToManagedRef(nat);
+    }
+
+    public static T NativeToManagedInlistNode<T>(IntPtr nat)
+    {
+        return GetTypeTraits<T>().NativeToManagedInlistNode(nat);
+    }
+
+    public static T NativeToManagedInplace<T>(IntPtr nat)
+    {
+        return GetTypeTraits<T>().NativeToManagedInplace(nat);
+    }
+
+    // Misc //
+
+    public static IntPtr EinaCompareCb<T>()
+    {
+        return GetTypeTraits<T>().EinaCompareCb();
+    }
+
+    public static IntPtr EinaFreeCb<T>()
+    {
+        return GetTypeTraits<T>().EinaFreeCb();
+    }
+
+    public static IntPtr EinaHashNew<TKey>()
+    {
+        return GetTypeTraits<TKey>().EinaHashNew();
+    }
+
+    public static IntPtr EinaInarrayNew<T>(uint step)
+    {
+        return GetTypeTraits<T>().EinaInarrayNew(step);
+    }
+
+    public static IntPtr EinaHashIteratorKeyNew<T>(IntPtr hash)
+    {
+        return GetTypeTraits<T>().EinaHashIteratorKeyNew(hash);
+    }
+}
+
+}
diff --git a/src/bindings/mono/eina_mono/eina_error.cs b/src/bindings/mono/eina_mono/eina_error.cs
new file mode 100644 (file)
index 0000000..7bd604e
--- /dev/null
@@ -0,0 +1,92 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace eina {
+
+public struct Error : IComparable<Error>
+{
+    int code;
+
+    public string Message
+    {
+        get { return MsgGet(this); }
+    }
+
+    public static Error EFL_ERROR;
+
+    public static Error NO_ERROR = new Error(0);
+    public static Error EPERM = new Error(1);
+    public static Error ENOENT = new Error(2);
+
+    public Error(int value) { code = value; }
+    static public implicit operator Error(int val)
+    {
+        return new Error(val);
+    }
+    static public implicit operator int(Error error)
+    {
+        return error.code;
+    }
+    public int CompareTo(Error err)
+    {
+        return code.CompareTo(err.code);
+    }
+    public override string ToString()
+    {
+        return "eina.Error(" + code + ")";
+    }
+
+    public static void Init()
+    {
+        if (eina_init() == 0)
+            throw (new efl.EflException("Failed to init Eina"));
+
+        EFL_ERROR = eina_error_msg_register("Managed Code Error");
+    }
+
+    [DllImport(efl.Libs.Eina)] private static extern int eina_init();
+    [DllImport(efl.Libs.Eina)] static extern Error eina_error_msg_register(string msg);
+    [DllImport(efl.Libs.Eina)] static extern Error eina_error_get();
+    [DllImport(efl.Libs.Eina)] static extern void eina_error_set(Error error);
+    [DllImport(efl.Libs.Eina)] static extern IntPtr eina_error_msg_get(Error error);
+
+    public static void Set(Error error)
+    {
+        eina_error_set(error);
+    }
+
+    public static Error Get()
+    {
+        return eina_error_get();
+    }
+
+    public static String MsgGet(Error error)
+    {
+        IntPtr cstr = eina_error_msg_get(error);
+        return eina.StringConversion.NativeUtf8ToManagedString(cstr);
+    }
+
+    public static void RaiseIfOccurred()
+    {
+        Error e = Get();
+        Clear();
+        Raise(e);
+    }
+
+    public static void Raise(Error e)
+    {
+        if (e != 0)
+            throw (new efl.EflException(MsgGet(e)));
+    }
+
+    public static void Clear()
+    {
+        Set(0);
+    }
+
+    public static Error Register(string msg)
+    {
+        return eina_error_msg_register(msg);
+    }
+}
+}
diff --git a/src/bindings/mono/eina_mono/eina_hash.cs b/src/bindings/mono/eina_mono/eina_hash.cs
new file mode 100644 (file)
index 0000000..045a9ae
--- /dev/null
@@ -0,0 +1,402 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+using static eina.TraitFunctions;
+using static eina.IteratorNativeFunctions;
+using static eina.HashNativeFunctions;
+using eina.Callbacks;
+
+namespace eina
+{
+
+[StructLayout(LayoutKind.Sequential)]
+public struct HashTupleNative
+{
+    public IntPtr key;
+    public IntPtr data;
+    public uint   key_length;
+}
+
+public static class HashNativeFunctions
+{
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_hash_new(IntPtr key_length_cb, IntPtr key_cmp_cb, IntPtr key_hash_cb, IntPtr data_free_cb, int buckets_power_size);
+
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_hash_free_cb_set(IntPtr hash, IntPtr data_free_cb);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_hash_string_djb2_new(IntPtr data_free_cb);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_hash_string_superfast_new(IntPtr data_free_cb);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_hash_string_small_new(IntPtr data_free_cb);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_hash_int32_new(IntPtr data_free_cb);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_hash_int64_new(IntPtr data_free_cb);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_hash_pointer_new(IntPtr data_free_cb);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_hash_stringshared_new(IntPtr data_free_cb);
+
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_hash_add(IntPtr hash, IntPtr key, IntPtr data);
+
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_hash_direct_add(IntPtr hash, IntPtr key, IntPtr data);
+
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_hash_del(IntPtr hash, IntPtr key, IntPtr data);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_hash_find(IntPtr hash, IntPtr key);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_hash_modify(IntPtr hash, IntPtr key, IntPtr data);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_hash_set(IntPtr hash, IntPtr key, IntPtr data);
+
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_hash_move(IntPtr hash, IntPtr old_key, IntPtr new_key);
+
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_hash_free(IntPtr hash);
+
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_hash_free_buckets(IntPtr hash);
+
+    [DllImport(efl.Libs.Eina)] public static extern int
+        eina_hash_population(IntPtr hash);
+
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_hash_add_by_hash(IntPtr hash, IntPtr key, int key_length, int key_hash, IntPtr data);
+
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_hash_direct_add_by_hash(IntPtr hash, IntPtr key, int key_length, int key_hash, IntPtr data);
+
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_hash_del_by_key_hash(IntPtr hash, IntPtr key, int key_length, int key_hash);
+
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_hash_del_by_key(IntPtr hash, IntPtr key);
+
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_hash_del_by_data(IntPtr hash, IntPtr data);
+
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_hash_del_by_hash(IntPtr hash, IntPtr key, int key_length, int key_hash, IntPtr data);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_hash_find_by_hash(IntPtr hash, IntPtr key, int key_length, int key_hash);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_hash_modify_by_hash(IntPtr hash, IntPtr key, int key_length, int key_hash, IntPtr data);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_hash_iterator_key_new(IntPtr hash);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_hash_iterator_data_new(IntPtr hash);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_hash_iterator_tuple_new(IntPtr hash);
+
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_hash_foreach(IntPtr hash, IntPtr func, IntPtr fdata);
+
+
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_hash_list_append(IntPtr hash, IntPtr key, IntPtr data);
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_hash_list_prepend(IntPtr hash, IntPtr key, IntPtr data);
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_hash_list_remove(IntPtr hash, IntPtr key, IntPtr data);
+
+    [DllImport(efl.Libs.Eina)] public static extern int
+        eina_hash_superfast(string key, int len);
+
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        eina_hash_iterator_ptr_key_wrapper_new_custom_export_mono(IntPtr hash);
+}
+
+public class Hash<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>, IDisposable
+{
+    public IntPtr Handle {get; set;} = IntPtr.Zero;
+    public bool Own {get; set;}
+    public bool OwnKey {get; set;}
+    public bool OwnValue {get; set;}
+
+    public int Count {
+        get {
+            return Population();
+        }
+    }
+
+
+    private void InitNew()
+    {
+        Handle = EinaHashNew<TKey>();
+        SetOwn(true);
+        SetOwnKey(true);
+        SetOwnValue(true);
+    }
+
+    public Hash()
+    {
+        InitNew();
+    }
+
+    public Hash(IntPtr handle, bool own)
+    {
+        Handle = handle;
+        SetOwnership(own);
+    }
+
+    public Hash(IntPtr handle, bool own, bool ownKey, bool ownValue)
+    {
+        Handle = handle;
+        SetOwnership(own, ownKey, ownValue);
+    }
+
+    ~Hash()
+    {
+        Dispose(false);
+    }
+
+    protected virtual void Dispose(bool disposing)
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        if (h == IntPtr.Zero)
+            return;
+
+        if (Own)
+            eina_hash_free(h);
+    }
+
+    public void Dispose()
+    {
+        Dispose(true);
+        GC.SuppressFinalize(this);
+    }
+
+    public void Free()
+    {
+        Dispose();
+    }
+
+    public IntPtr Release()
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        return h;
+    }
+
+    public void SetOwn(bool own)
+    {
+        Own = own;
+    }
+
+    public void SetOwnKey(bool ownKey)
+    {
+        OwnKey = ownKey;
+    }
+
+    public void SetOwnValue(bool ownValue)
+    {
+        OwnValue = ownValue;
+
+        if (ownValue)
+            eina_hash_free_cb_set(Handle, EinaFreeCb<TValue>());
+    }
+
+    public void SetOwnership(bool ownAll)
+    {
+        SetOwn(ownAll);
+        SetOwnKey(ownAll);
+        SetOwnValue(ownAll);
+    }
+
+    public void SetOwnership(bool own, bool ownKey, bool ownValue)
+    {
+        SetOwn(own);
+        SetOwnKey(ownKey);
+        SetOwnValue(ownValue);
+    }
+
+    public void UnSetFreeCb()
+    {
+        eina_hash_free_cb_set(Handle, IntPtr.Zero);
+    }
+
+    public bool AddNew(TKey key, TValue val)
+    {
+        var nk = ManagedToNativeAllocRef(key, true);
+        var nv = ManagedToNativeAlloc(val);
+        var r = eina_hash_add(Handle, nk, nv);
+        NativeFreeRef<TKey>(nk);
+        return r;
+    }
+
+    public void Add(TKey key, TValue val)
+    {
+        Set(key, val);
+    }
+
+    public bool DelByKey(TKey key)
+    {
+        var nk = ManagedToNativeAllocRef(key);
+        var r = eina_hash_del_by_key(Handle, nk);
+        NativeFreeRef<TKey>(nk, OwnKey && r);
+        return r;
+    }
+
+    public bool DelByValue(TValue val)
+    {
+        var nv = ManagedToNativeAlloc(val);
+        var r = eina_hash_del_by_data(Handle, nv);
+        NativeFree<TValue>(nv);
+        return r;
+    }
+
+    public void Remove(TKey key)
+    {
+        DelByKey(key);
+    }
+
+    public TValue Find(TKey key)
+    {
+        var nk = ManagedToNativeAllocRef(key);
+        var found = eina_hash_find(Handle, nk);
+        NativeFreeRef<TKey>(nk);
+        if (found == IntPtr.Zero)
+            throw new KeyNotFoundException();
+        return NativeToManaged<TValue>(found);
+    }
+
+    public bool TryGetValue(TKey key, out TValue val)
+    {
+        var nk = ManagedToNativeAllocRef(key);
+        var found = eina_hash_find(Handle, nk);
+        NativeFreeRef<TKey>(nk);
+        if (found == IntPtr.Zero)
+        {
+            val = default(TValue);
+            return false;
+        }
+        val = NativeToManaged<TValue>(found);
+        return true;
+    }
+
+    public bool ContainsKey(TKey key)
+    {
+        var nk = ManagedToNativeAllocRef(key);
+        var found = eina_hash_find(Handle, nk);
+        NativeFreeRef<TKey>(nk);
+        return found != IntPtr.Zero;
+    }
+
+    public bool Modify(TKey key, TValue val)
+    {
+        var nk = ManagedToNativeAllocRef(key);
+        var nv = ManagedToNativeAlloc(val);
+        var old = eina_hash_modify(Handle, nk, nv);
+        NativeFreeRef<TKey>(nk);
+        if (old == IntPtr.Zero)
+        {
+            NativeFree<TValue>(nv);
+            return false;
+        }
+        if (OwnValue)
+            NativeFree<TValue>(old);
+        return true;
+    }
+
+    public void Set(TKey key, TValue val)
+    {
+        var nk = ManagedToNativeAllocRef(key, true);
+        var nv = ManagedToNativeAlloc(val);
+        var old = eina_hash_set(Handle, nk, nv);
+        NativeFreeRef<TKey>(nk, old != IntPtr.Zero);
+        if (old != IntPtr.Zero && OwnValue)
+            NativeFree<TValue>(old);
+    }
+
+    public TValue this[TKey key]
+    {
+        get
+        {
+            return Find(key);
+        }
+        set
+        {
+            Set(key, value);
+        }
+    }
+
+    public bool Move(TKey key_old, TKey key_new)
+    {
+        var nk_old = ManagedToNativeAllocRef(key_old);
+        var nk_new = ManagedToNativeAllocRef(key_new, true);
+        var r = eina_hash_move(Handle, nk_old, nk_new);
+        NativeFreeRef<TKey>(nk_old, OwnKey && r);
+        NativeFreeRef<TKey>(nk_new, !r);
+        return r;
+    }
+
+    public void FreeBuckets()
+    {
+        eina_hash_free_buckets(Handle);
+    }
+
+    public int Population()
+    {
+        return eina_hash_population(Handle);
+    }
+
+    public eina.Iterator<TKey> Keys()
+    {
+        return new eina.Iterator<TKey>(EinaHashIteratorKeyNew<TKey>(Handle), true, false);
+    }
+
+    public eina.Iterator<TValue> Values()
+    {
+        return new eina.Iterator<TValue>(eina_hash_iterator_data_new(Handle), true, false);
+    }
+
+    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
+    {
+        IntPtr itr = eina_hash_iterator_tuple_new(Handle);
+        try
+        {
+            for (IntPtr tuplePtr; eina_iterator_next(itr, out tuplePtr);)
+            {
+                var tuple = Marshal.PtrToStructure<eina.HashTupleNative>(tuplePtr);
+                var key = NativeToManagedRef<TKey>(tuple.key);
+                var val = NativeToManaged<TValue>(tuple.data);
+                yield return new KeyValuePair<TKey, TValue>(key, val);
+            }
+        }
+        finally
+        {
+            eina_iterator_free(itr);
+        }
+    }
+
+    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+    {
+        return this.GetEnumerator();
+    }
+}
+
+}
+
diff --git a/src/bindings/mono/eina_mono/eina_inarray.cs b/src/bindings/mono/eina_mono/eina_inarray.cs
new file mode 100644 (file)
index 0000000..120a4b8
--- /dev/null
@@ -0,0 +1,324 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+using static eina.TraitFunctions;
+using static eina.InarrayNativeFunctions;
+
+namespace eina {
+
+public static class InarrayNativeFunctions
+{
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inarray_new(uint member_size, uint step);
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_inarray_free(IntPtr array);
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_inarray_step_set(IntPtr array, uint sizeof_eina_inarray, uint member_size, uint step);
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_inarray_flush(IntPtr array);
+    [DllImport(efl.Libs.Eina)] public static extern int
+        eina_inarray_push(IntPtr array, IntPtr data);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inarray_grow(IntPtr array, uint size);
+    [DllImport(efl.Libs.Eina)] public static extern int
+        eina_inarray_insert(IntPtr array, IntPtr data, IntPtr compare);
+    [DllImport(efl.Libs.Eina)] public static extern int
+        eina_inarray_insert_sorted(IntPtr array, IntPtr data, IntPtr compare);
+    [DllImport(efl.Libs.Eina)] public static extern int
+        eina_inarray_remove(IntPtr array, IntPtr data);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inarray_pop(IntPtr array);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inarray_nth(IntPtr array, uint position);
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_inarray_insert_at(IntPtr array, uint position, IntPtr data);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inarray_alloc_at(IntPtr array, uint position, uint member_count);
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_inarray_replace_at(IntPtr array, uint position, IntPtr data);
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_inarray_remove_at(IntPtr array, uint position);
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_inarray_reverse(IntPtr array);
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_inarray_sort(IntPtr array, IntPtr compare);
+    [DllImport(efl.Libs.Eina)] public static extern int
+        eina_inarray_search(IntPtr array, IntPtr data, IntPtr compare);
+    [DllImport(efl.Libs.Eina)] public static extern int
+        eina_inarray_search_sorted(IntPtr array, IntPtr data, IntPtr compare);
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_inarray_foreach(IntPtr array, IntPtr function, IntPtr user_data);
+    [DllImport(efl.Libs.Eina)] public static extern int
+        eina_inarray_foreach_remove(IntPtr array, IntPtr match, IntPtr user_data);
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_inarray_resize(IntPtr array, uint new_size);
+    [DllImport(efl.Libs.Eina)] public static extern uint
+        eina_inarray_count(IntPtr array);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inarray_iterator_new(IntPtr array);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inarray_iterator_reversed_new(IntPtr array);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inarray_accessor_new(IntPtr array);
+}
+
+public class Inarray<T> : IEnumerable<T>, IDisposable
+{
+    public static uint DefaultStep = 0;
+
+    public IntPtr Handle {get;set;} = IntPtr.Zero;
+    public bool Own {get;set;}
+    public bool OwnContent {get;set;}
+
+    public int Length
+    {
+        get { return Count(); }
+    }
+
+
+    private void InitNew(uint step)
+    {
+        Handle = EinaInarrayNew<T>(step);
+        Own = true;
+        OwnContent = true;
+        if (Handle == IntPtr.Zero)
+            throw new SEHException("Could not alloc inarray");
+    }
+
+    public Inarray()
+    {
+        InitNew(DefaultStep);
+    }
+
+    public Inarray(uint step)
+    {
+        InitNew(step);
+    }
+
+    public Inarray(IntPtr handle, bool own)
+    {
+        Handle = handle;
+        Own = own;
+        OwnContent = own;
+    }
+
+    public Inarray(IntPtr handle, bool own, bool ownContent)
+    {
+        Handle = handle;
+        Own = own;
+        OwnContent = ownContent;
+    }
+
+    ~Inarray()
+    {
+        Dispose(false);
+    }
+
+    protected virtual void Dispose(bool disposing)
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        if (h == IntPtr.Zero)
+            return;
+
+        if (OwnContent)
+        {
+            uint len = eina_inarray_count(h);
+            for(uint i = 0; i < len; ++i)
+            {
+                NativeFreeInplace<T>(eina_inarray_nth(h, i));
+            }
+        }
+
+        if (Own)
+            eina_inarray_free(h);
+    }
+
+    public void Dispose()
+    {
+        Dispose(true);
+        GC.SuppressFinalize(this);
+    }
+
+    public void Free()
+    {
+        Dispose();
+    }
+
+    public IntPtr Release()
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        return h;
+    }
+
+    private void FreeElementsIfOwned()
+    {
+        if (OwnContent)
+        {
+            int len = Length;
+            for (int i = 0; i < len; ++i)
+            {
+                NativeFreeInplace<T>(eina_inarray_nth(Handle, (uint)i));
+            }
+        }
+    }
+
+    public void Flush()
+    {
+        FreeElementsIfOwned();
+        eina_inarray_flush(Handle);
+    }
+
+    public int Count()
+    {
+        return (int) eina_inarray_count(Handle);
+    }
+
+    public void SetOwnership(bool ownAll)
+    {
+        Own = ownAll;
+        OwnContent = ownAll;
+    }
+
+    public void SetOwnership(bool own, bool ownContent)
+    {
+        Own = own;
+        OwnContent = ownContent;
+    }
+
+    public int Push(T val)
+    {
+        IntPtr ele = ManagedToNativeAllocInplace(val);
+        var r = eina_inarray_push(Handle, ele);
+        if (r == -1)
+            NativeFreeInplace<T>(ele);
+        ResidueFreeInplace<T>(ele);
+        return r;
+    }
+
+// TODO ???
+//     public void Add(T val)
+//     {
+//         if (!Push(val))
+//           throw;
+//     }
+
+    public T Pop()
+    {
+        IntPtr ele = eina_inarray_pop(Handle);
+        var r = NativeToManagedInplace<T>(ele);
+        if (OwnContent && ele != IntPtr.Zero)
+            NativeFreeInplace<T>(ele);
+        return r;
+    }
+
+    public T Nth(uint idx)
+    {
+        IntPtr ele = eina_inarray_nth(Handle, idx);
+        return NativeToManagedInplace<T>(ele);
+    }
+
+    public T At(int idx)
+    {
+        return Nth((uint)idx);
+    }
+
+    public bool InsertAt(uint idx, T val)
+    {
+        IntPtr ele = ManagedToNativeAllocInplace(val);
+        var r = eina_inarray_insert_at(Handle, idx, ele);
+        if (!r)
+            NativeFreeInplace<T>(ele);
+        ResidueFreeInplace<T>(ele);
+        return r;
+    }
+
+    public bool ReplaceAt(uint idx, T val)
+    {
+        var old = eina_inarray_nth(Handle, idx);
+        if (old == IntPtr.Zero)
+            return false;
+        if (OwnContent)
+            NativeFreeInplace<T>(old);
+        var ele = ManagedToNativeAllocInplace(val);
+        var r = eina_inarray_replace_at(Handle, idx, ele);
+        ResidueFreeInplace<T>(ele);
+        return r;
+    }
+
+    public T this[int idx]
+    {
+        get
+        {
+            return At(idx);
+        }
+        set
+        {
+            ReplaceAt((uint)idx, value);
+        }
+    }
+
+    public bool RemoveAt(uint idx)
+    {
+        IntPtr ele = eina_inarray_nth(Handle, idx);
+        if (ele == IntPtr.Zero)
+            return false;
+        if (OwnContent)
+            NativeFreeInplace<T>(ele);
+
+        return eina_inarray_remove_at(Handle, idx);
+    }
+
+    public void Reverse()
+    {
+        eina_inarray_reverse(Handle);
+    }
+
+    public T[] ToArray()
+    {
+        int len = Length;
+        var managed = new T[len];
+        for(int i = 0; i < len; ++i)
+        {
+            managed[i] = At(i);
+        }
+        return managed;
+    }
+
+    public bool Append(T[] values)
+    {
+        foreach(T v in values)
+            if (Push(v) == -1)
+                return false;
+        return true;
+    }
+
+    public eina.Iterator<T> GetIterator()
+    {
+        return new eina.Iterator<T>(eina_inarray_iterator_new(Handle), true, false);
+    }
+
+    public eina.Iterator<T> GetReversedIterator()
+    {
+        return new eina.Iterator<T>(eina_inarray_iterator_reversed_new(Handle), true, false);
+    }
+
+    public IEnumerator<T> GetEnumerator()
+    {
+        int len = Length;
+        for(int i = 0; i < len; ++i)
+        {
+            yield return At(i);
+        }
+    }
+
+    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+    {
+        return this.GetEnumerator();
+    }
+}
+
+}
diff --git a/src/bindings/mono/eina_mono/eina_inlist.cs b/src/bindings/mono/eina_mono/eina_inlist.cs
new file mode 100644 (file)
index 0000000..8257c20
--- /dev/null
@@ -0,0 +1,316 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+using static eina.TraitFunctions;
+using static eina.InlistNativeFunctions;
+using eina.Callbacks;
+
+namespace eina {
+
+public static class InlistNativeFunctions
+{
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inlist_append(IntPtr in_list, IntPtr in_item);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inlist_prepend(IntPtr in_list, IntPtr in_item);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inlist_append_relative(IntPtr in_list, IntPtr in_item, IntPtr in_relative);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inlist_prepend_relative(IntPtr in_list, IntPtr in_item, IntPtr in_relative);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inlist_remove(IntPtr in_list, IntPtr in_item);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inlist_find(IntPtr in_list, IntPtr in_item);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inlist_promote(IntPtr list, IntPtr item);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inlist_demote(IntPtr list, IntPtr item);
+
+    [DllImport(efl.Libs.Eina)] public static extern uint
+        eina_inlist_count(IntPtr list);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inlist_iterator_new(IntPtr in_list);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inlist_accessor_new(IntPtr in_list);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inlist_sorted_insert(IntPtr list, IntPtr item, IntPtr func);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inlist_sorted_state_new();
+
+    [DllImport(efl.Libs.Eina)] public static extern int
+        eina_inlist_sorted_state_init(IntPtr state, IntPtr list);
+
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_inlist_sorted_state_free(IntPtr state);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inlist_sorted_state_insert(IntPtr list, IntPtr item, IntPtr func, IntPtr state);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_inlist_sort(IntPtr head, IntPtr func);
+
+
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        eina_inlist_first_custom_export_mono(IntPtr list);
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        eina_inlist_last_custom_export_mono(IntPtr list);
+
+
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        eina_inlist_next_custom_export_mono(IntPtr list);
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        eina_inlist_prev_custom_export_mono(IntPtr list);
+
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        eina_inlist_iterator_wrapper_new_custom_export_mono(IntPtr in_list);
+}
+
+public class Inlist<T> : IEnumerable<T>, IDisposable
+{
+    public IntPtr Handle {get;set;} = IntPtr.Zero;
+    public bool Own {get;set;}
+    public bool OwnContent {get;set;}
+
+    public int Length
+    {
+        get { return Count(); }
+    }
+
+
+    private void InitNew()
+    {
+        Handle = IntPtr.Zero;
+        Own = true;
+        OwnContent = true;
+    }
+
+    private IntPtr InternalFirst()
+    {
+        return eina_inlist_first_custom_export_mono(Handle);
+    }
+
+    private IntPtr InternalLast()
+    {
+        return eina_inlist_last_custom_export_mono(Handle);
+    }
+
+    private IntPtr InternalAt(int idx)
+    {
+        if (idx < 0)
+            return IntPtr.Zero;
+
+        IntPtr curr = Handle;
+        for (int n = 0; n != idx && curr != IntPtr.Zero; ++n)
+            curr = InternalNext(curr);
+        return curr;
+    }
+
+    private static IntPtr InternalNext(IntPtr inlist)
+    {
+        return eina_inlist_next_custom_export_mono(inlist);
+    }
+
+    private static IntPtr InternalPrev(IntPtr inlist)
+    {
+        return eina_inlist_prev_custom_export_mono(inlist);
+    }
+
+
+    public Inlist()
+    {
+        InitNew();
+    }
+
+    public Inlist(IntPtr handle, bool own)
+    {
+        Handle = handle;
+        Own = own;
+        OwnContent = own;
+    }
+
+    public Inlist(IntPtr handle, bool own, bool ownContent)
+    {
+        Handle = handle;
+        Own = own;
+        OwnContent = ownContent;
+    }
+
+    ~Inlist()
+    {
+        Dispose(false);
+    }
+
+    protected virtual void Dispose(bool disposing)
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        if (h == IntPtr.Zero)
+            return;
+
+        if (OwnContent)
+        {
+            for(IntPtr curr = h; curr != IntPtr.Zero; curr = InternalNext(curr))
+            {
+                NativeFreeInlistNodeElement<T>(curr);
+            }
+        }
+
+        if (Own)
+        {
+            while (h != IntPtr.Zero)
+            {
+                var aux = h;
+                h = eina_inlist_remove(h, h);
+                NativeFreeInlistNode<T>(aux, false);
+            }
+        }
+    }
+
+    public void Dispose()
+    {
+        Dispose(true);
+        GC.SuppressFinalize(this);
+    }
+
+    public void Free()
+    {
+        Dispose();
+    }
+
+    public IntPtr Release()
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        return h;
+    }
+
+    public void SetOwnership(bool ownAll)
+    {
+        Own = ownAll;
+        OwnContent = ownAll;
+    }
+
+    public void SetOwnership(bool own, bool ownContent)
+    {
+        Own = own;
+        OwnContent = ownContent;
+    }
+
+    public int Count()
+    {
+        return (int) eina_inlist_count(Handle);
+    }
+
+    public void Clean()
+    {
+        while (Handle != IntPtr.Zero)
+        {
+            var aux = Handle;
+            Handle = eina_inlist_remove(Handle, Handle);
+            NativeFreeInlistNode<T>(aux, OwnContent);
+        }
+    }
+
+    public void Append(T val)
+    {
+        IntPtr node = ManagedToNativeAllocInlistNode(val);
+        Handle = eina_inlist_append(Handle, node);
+    }
+
+    public void Prepend(T val)
+    {
+        IntPtr node = ManagedToNativeAllocInlistNode(val);
+        Handle = eina_inlist_prepend(Handle, node);
+    }
+
+    public void Remove(int idx)
+    {
+        IntPtr node = InternalAt(idx);
+        Handle = eina_inlist_remove(Handle, node);
+        NativeFreeInlistNode<T>(node, OwnContent);
+    }
+
+    public T At(int idx)
+    {
+        IntPtr node = InternalAt(idx);
+        if (node == IntPtr.Zero)
+            throw new IndexOutOfRangeException();
+        return NativeToManagedInlistNode<T>(node);
+    }
+
+    public void DataSet(int idx, T val)
+    {
+        IntPtr old = InternalAt(idx);
+        if (old == IntPtr.Zero)
+            throw new IndexOutOfRangeException();
+
+        IntPtr new_node = ManagedToNativeAllocInlistNode(val);
+
+        Handle = eina_inlist_append_relative(Handle, new_node, old);
+        Handle = eina_inlist_remove(Handle, old);
+
+        NativeFreeInlistNode<T>(old, OwnContent);
+    }
+
+    public T this[int idx]
+    {
+        get
+        {
+            return At(idx);
+        }
+        set
+        {
+            DataSet(idx, value);
+        }
+    }
+
+    public T[] ToArray()
+    {
+        var managed = new T[Count()];
+        int i = 0;
+        for(IntPtr curr = Handle; curr != IntPtr.Zero; ++i, curr = InternalNext(curr))
+        {
+            managed[i] = NativeToManagedInlistNode<T>(curr);
+        }
+        return managed;
+    }
+
+    public void AppendArray(T[] values)
+    {
+        foreach (T v in values)
+            Append(v);
+    }
+
+
+    public eina.Iterator<T> GetIterator()
+    {
+        return new eina.Iterator<T>(eina_inlist_iterator_wrapper_new_custom_export_mono(Handle), true, false);
+    }
+
+    public IEnumerator<T> GetEnumerator()
+    {
+        for(IntPtr curr = Handle; curr != IntPtr.Zero; curr = InternalNext(curr))
+        {
+            yield return NativeToManagedInlistNode<T>(curr);
+        }
+    }
+
+    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+    {
+        return this.GetEnumerator();
+    }
+}
+
+}
diff --git a/src/bindings/mono/eina_mono/eina_iterator.cs b/src/bindings/mono/eina_mono/eina_iterator.cs
new file mode 100644 (file)
index 0000000..854a68c
--- /dev/null
@@ -0,0 +1,144 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+using static eina.TraitFunctions;
+using static eina.IteratorNativeFunctions;
+
+namespace eina {
+
+public static class IteratorNativeFunctions
+{
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_iterator_free(IntPtr iterator);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_iterator_container_get(IntPtr iterator);
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_iterator_next(IntPtr iterator, out IntPtr data);
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_iterator_foreach(IntPtr iterator, IntPtr callback, IntPtr fdata);
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_iterator_lock(IntPtr iterator);
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_iterator_unlock(IntPtr iterator);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_carray_iterator_new(IntPtr array);
+}
+
+public class Iterator<T> : IEnumerable<T>, IDisposable
+{
+    public IntPtr Handle {get;set;} = IntPtr.Zero;
+    public bool Own {get;set;} = true;
+    public bool OwnContent {get;set;} = false;
+
+    public Iterator(IntPtr handle, bool own)
+    {
+        Handle = handle;
+        Own = own;
+        OwnContent = own;
+    }
+
+    public Iterator(IntPtr handle, bool own, bool ownContent)
+    {
+        Handle = handle;
+        Own = own;
+        OwnContent = ownContent;
+    }
+
+    ~Iterator()
+    {
+        Dispose(false);
+    }
+
+    protected virtual void Dispose(bool disposing)
+    {
+        var h = Handle;
+        Handle = IntPtr.Zero;
+        if (h == IntPtr.Zero)
+            return;
+
+        if (OwnContent)
+        {
+            for(IntPtr data; eina_iterator_next(h, out data);)
+            {
+                NativeFree<T>(data);
+            }
+        }
+
+        if (Own)
+            eina_iterator_free(h);
+    }
+
+    public void Dispose()
+    {
+        Dispose(true);
+        GC.SuppressFinalize(this);
+    }
+
+    public void Free()
+    {
+        Dispose();
+    }
+
+    public IntPtr Release()
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        return h;
+    }
+
+    public void SetOwnership(bool ownAll)
+    {
+        Own = ownAll;
+        OwnContent = ownAll;
+    }
+
+    public void SetOwnership(bool own, bool ownContent)
+    {
+        Own = own;
+        OwnContent = ownContent;
+    }
+
+    public bool Next(out T res)
+    {
+        IntPtr data;
+        if (!eina_iterator_next(Handle, out data))
+        {
+            res = default(T);
+            return false;
+        }
+
+        res = NativeToManaged<T>(data);
+
+        if (OwnContent)
+            NativeFree<T>(data);
+
+        return true;
+    }
+
+    public bool Lock()
+    {
+        return eina_iterator_lock(Handle);
+    }
+
+    public bool Unlock()
+    {
+        return eina_iterator_unlock(Handle);
+    }
+
+    public IEnumerator<T> GetEnumerator()
+    {
+        for(T curr; Next(out curr);)
+        {
+            yield return curr;
+        }
+    }
+
+    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+    {
+        return this.GetEnumerator();
+    }
+}
+
+}
diff --git a/src/bindings/mono/eina_mono/eina_list.cs b/src/bindings/mono/eina_mono/eina_list.cs
new file mode 100644 (file)
index 0000000..c972c82
--- /dev/null
@@ -0,0 +1,352 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+using static eina.TraitFunctions;
+using static eina.ListNativeFunctions;
+using eina.Callbacks;
+
+namespace eina {
+
+public static class ListNativeFunctions
+{
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_append(IntPtr list, IntPtr data);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_prepend(IntPtr list, IntPtr data);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_append_relative(IntPtr list, IntPtr data, IntPtr relative);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_append_relative_list(IntPtr list, IntPtr data, IntPtr relative);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_prepend_relative(IntPtr list, IntPtr data, IntPtr relative);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_prepend_relative_list(IntPtr list, IntPtr data, IntPtr relative);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_sorted_insert(IntPtr list, IntPtr func, IntPtr data);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_remove(IntPtr list, IntPtr data);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_remove_list(IntPtr list, IntPtr remove_list);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_promote_list(IntPtr list, IntPtr move_list);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_demote_list(IntPtr list, IntPtr move_list);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_data_find(IntPtr list, IntPtr data);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_data_find_list(IntPtr list, IntPtr data);
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_list_move(ref IntPtr to, ref IntPtr from, IntPtr data);
+    [DllImport(efl.Libs.Eina)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eina_list_move_list(ref IntPtr to, ref IntPtr from, IntPtr data);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_free(IntPtr list);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_nth(IntPtr list, uint n);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_nth_list(IntPtr list, uint n);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_reverse(IntPtr list);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_reverse_clone(IntPtr list);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_clone(IntPtr list);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_sort(IntPtr list, uint limit, IntPtr func);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_shuffle(IntPtr list, IntPtr func);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_merge(IntPtr left, IntPtr right);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_sorted_merge(IntPtr left, IntPtr right, IntPtr func);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_split_list(IntPtr list, IntPtr relative, ref IntPtr right);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_search_sorted_near_list(IntPtr list, IntPtr func, IntPtr data, IntPtr result_cmp);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_search_sorted_list(IntPtr list, IntPtr func, IntPtr data);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_search_sorted(IntPtr list, IntPtr func, IntPtr data);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_search_unsorted_list(IntPtr list, IntPtr func, IntPtr data);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_search_unsorted(IntPtr list, IntPtr func, IntPtr data);
+
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_iterator_new(IntPtr list);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_iterator_reversed_new(IntPtr list);
+    [DllImport(efl.Libs.Eina)] public static extern IntPtr
+        eina_list_accessor_new(IntPtr list);
+    [DllImport(efl.Libs.Eina)] public static extern int
+        eina_list_data_idx(IntPtr list, IntPtr data);
+
+
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        eina_list_last_custom_export_mono(IntPtr list);
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        eina_list_next_custom_export_mono(IntPtr list);
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        eina_list_prev_custom_export_mono(IntPtr list);
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        eina_list_data_get_custom_export_mono(IntPtr list);
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        eina_list_data_set_custom_export_mono(IntPtr list, IntPtr data);
+    [DllImport(efl.Libs.CustomExports)] public static extern uint
+        eina_list_count_custom_export_mono(IntPtr list);
+    [DllImport(efl.Libs.CustomExports)] public static extern IntPtr
+        eina_list_last_data_get_custom_export_mono(IntPtr list);
+}
+
+public class List<T> : IEnumerable<T>, IDisposable
+{
+    public IntPtr Handle {get;set;} = IntPtr.Zero;
+    public bool Own {get;set;}
+    public bool OwnContent {get;set;}
+
+    public int Length
+    {
+        get { return Count(); }
+    }
+
+
+    private void InitNew()
+    {
+        Handle = IntPtr.Zero;
+        Own = true;
+        OwnContent = true;
+    }
+
+    private IntPtr InternalLast()
+    {
+        return eina_list_last_custom_export_mono(Handle);
+    }
+
+    private static IntPtr InternalNext(IntPtr list)
+    {
+        return eina_list_next_custom_export_mono(list);
+    }
+
+    private static IntPtr InternalPrev(IntPtr list)
+    {
+        return eina_list_prev_custom_export_mono(list);
+    }
+
+    private static IntPtr InternalDataGet(IntPtr list)
+    {
+        return eina_list_data_get_custom_export_mono(list);
+    }
+
+    private static IntPtr InternalDataSet(IntPtr list, IntPtr data)
+    {
+        return eina_list_data_set_custom_export_mono(list, data);
+    }
+
+
+    public List()
+    {
+        InitNew();
+    }
+
+    public List(IntPtr handle, bool own)
+    {
+        Handle = handle;
+        Own = own;
+        OwnContent = own;
+    }
+
+    public List(IntPtr handle, bool own, bool ownContent)
+    {
+        Handle = handle;
+        Own = own;
+        OwnContent = ownContent;
+    }
+
+    ~List()
+    {
+        Dispose(false);
+    }
+
+    protected virtual void Dispose(bool disposing)
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        if (h == IntPtr.Zero)
+            return;
+
+        if (OwnContent)
+        {
+            for(IntPtr curr = h; curr != IntPtr.Zero; curr = InternalNext(curr))
+            {
+                NativeFree<T>(InternalDataGet(curr));
+            }
+        }
+
+        if (Own)
+            eina_list_free(h);
+    }
+
+    public void Dispose()
+    {
+        Dispose(true);
+        GC.SuppressFinalize(this);
+    }
+
+    public void Free()
+    {
+        Dispose();
+    }
+
+    public IntPtr Release()
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        return h;
+    }
+
+    public void SetOwnership(bool ownAll)
+    {
+        Own = ownAll;
+        OwnContent = ownAll;
+    }
+
+    public void SetOwnership(bool own, bool ownContent)
+    {
+        Own = own;
+        OwnContent = ownContent;
+    }
+
+    public int Count()
+    {
+        return (int) eina_list_count_custom_export_mono(Handle);
+    }
+
+    public void Append(T val)
+    {
+        IntPtr ele = ManagedToNativeAlloc(val);
+        Handle = eina_list_append(Handle, ele);
+    }
+
+    public void Prepend(T val)
+    {
+        IntPtr ele = ManagedToNativeAlloc(val);
+        Handle = eina_list_prepend(Handle, ele);
+    }
+
+    public void SortedInsert(T val)
+    {
+        IntPtr ele = ManagedToNativeAlloc(val);
+        Handle = eina_list_sorted_insert(Handle, EinaCompareCb<T>(), ele);
+    }
+
+    public void SortedInsert(Eina_Compare_Cb compareCb, T val)
+    {
+        IntPtr ele = ManagedToNativeAlloc(val);
+        Handle = eina_list_sorted_insert(Handle, Marshal.GetFunctionPointerForDelegate(compareCb), ele);
+    }
+
+    public void Sort(int limit = 0)
+    {
+        Handle = eina_list_sort(Handle, (uint)limit, EinaCompareCb<T>());
+    }
+
+    public void Sort(Eina_Compare_Cb compareCb)
+    {
+        Handle = eina_list_sort(Handle, 0, Marshal.GetFunctionPointerForDelegate(compareCb));
+    }
+
+    public void Sort(int limit, Eina_Compare_Cb compareCb)
+    {
+        Handle = eina_list_sort(Handle, (uint)limit, Marshal.GetFunctionPointerForDelegate(compareCb));
+    }
+
+    public T Nth(int n)
+    {
+        // TODO: check bounds ???
+        IntPtr ele = eina_list_nth(Handle, (uint)n);
+        return NativeToManaged<T>(ele);
+    }
+
+    public void DataSet(int idx, T val)
+    {
+        IntPtr pos = eina_list_nth_list(Handle, (uint)idx);
+        if (pos == IntPtr.Zero)
+            throw new IndexOutOfRangeException();
+        if (OwnContent)
+            NativeFree<T>(InternalDataGet(pos));
+        IntPtr ele = ManagedToNativeAlloc(val);
+        InternalDataSet(pos, ele);
+    }
+
+    public T this[int idx]
+    {
+        get
+        {
+            return Nth(idx);
+        }
+        set
+        {
+            DataSet(idx, value);
+        }
+    }
+
+    public T LastDataGet()
+    {
+        IntPtr ele = eina_list_last_data_get_custom_export_mono(Handle);
+        return NativeToManaged<T>(ele);
+    }
+
+    public void Reverse()
+    {
+        Handle = eina_list_reverse(Handle);
+    }
+
+    public void Shuffle()
+    {
+        Handle = eina_list_shuffle(Handle, IntPtr.Zero);
+    }
+
+    public T[] ToArray()
+    {
+        var managed = new T[Count()];
+        int i = 0;
+        for(IntPtr curr = Handle; curr != IntPtr.Zero; curr = InternalNext(curr), ++i)
+        {
+            managed[i] = NativeToManaged<T>(InternalDataGet(curr));
+        }
+        return managed;
+    }
+
+    public void AppendArray(T[] values)
+    {
+        foreach (T v in values)
+            Append(v);
+    }
+
+
+    public eina.Iterator<T> GetIterator()
+    {
+        return new eina.Iterator<T>(eina_list_iterator_new(Handle), true, false);
+    }
+
+    public eina.Iterator<T> GetReversedIterator()
+    {
+        return new eina.Iterator<T>(eina_list_iterator_reversed_new(Handle), true, false);
+    }
+
+    public IEnumerator<T> GetEnumerator()
+    {
+        for(IntPtr curr = Handle; curr != IntPtr.Zero; curr = InternalNext(curr))
+        {
+            yield return NativeToManaged<T>(InternalDataGet(curr));
+        }
+    }
+
+    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+    {
+        return this.GetEnumerator();
+    }
+}
+
+}
diff --git a/src/bindings/mono/eina_mono/eina_log.cs b/src/bindings/mono/eina_mono/eina_log.cs
new file mode 100644 (file)
index 0000000..a2a1e45
--- /dev/null
@@ -0,0 +1,121 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.CompilerServices;
+using System.Diagnostics.Contracts;
+
+namespace eina { // Manual wrappers around eina functions
+
+public class Log
+{
+    [DllImport(efl.Libs.Eina)] private static extern int eina_init();
+
+    [DllImport(efl.Libs.Eina)] private static extern void eina_log_print(
+            int domain,
+            Level level,
+            [MarshalAs(UnmanagedType.LPStr)] String file,
+            [MarshalAs(UnmanagedType.LPStr)] String function,
+            int line,
+            [MarshalAs(UnmanagedType.LPStr)] String message);
+
+    [DllImport(efl.Libs.Eina)] private static extern int eina_log_domain_register(
+            [MarshalAs(UnmanagedType.LPStr)] String name,
+            [MarshalAs(UnmanagedType.LPStr)] String color);
+
+    [DllImport(efl.Libs.Eina)] private static extern void eina_log_level_set(Level level);
+
+    [DllImport(efl.Libs.Eina)] private static extern Level eina_log_level_get();
+
+    public enum Level
+    {
+        Critical,
+        Error,
+        Warning,
+        Info,
+        Debug,
+        Unkown = (-2147483647 - 1)
+    }
+
+    public class Color
+    {
+        public static string LIGHTRED  = "\033[31;1m";
+        public static string RED       = "\033[31m";
+        public static string LIGHTBLUE = "\033[34;1m";
+        public static string BLUE      = "\033[34m";
+        public static string GREEN     = "\033[32;1m";
+        public static string YELLOW    = "\033[33;1m";
+        public static string ORANGE    = "\033[0;33m";
+        public static string WHITE     = "\033[37;1m";
+        public static string LIGHTCYAN = "\033[36;1m";
+        public static string CYAN      = "\033[36m";
+        public static string RESET     = "\033[0m";
+        public static string HIGH      = "\033[1m";
+    }
+
+    private static int domain = -1;
+
+    public static void Init(String name="mono", String color="\033[32;1m")
+    {
+        if (domain == -1)
+          {
+              // Maybe move this check outside when other eina stuff get support?
+              if (eina_init() == 0)
+                {
+                   Console.WriteLine("Error: Can't initialize Eina for logging.");
+                   return;
+                }
+              domain = eina_log_domain_register(name, color);
+              if (domain < 0)
+                Console.WriteLine("Error: Couldn't register Eina log domain for name {0}.", name);
+              else
+                Info($"Registered mono domain with number {domain}");
+          }
+        else
+          {
+              Warning("Trying to initialize the log system again.");
+              // TODO Export the domain registration to the binding user to allow custom domains.
+          }
+    }
+
+    private static void EnsureDomainRegistered()
+    {
+        if (domain < 0)
+          throw new InvalidOperationException("Log domain is not registered.");
+    }
+
+    public static void Critical(String message, [CallerLineNumber] int line=0, [CallerFilePath] string file=null, [CallerMemberName] string member = null)
+    {
+        EnsureDomainRegistered();
+        eina_log_print(domain, Level.Critical, file, member, line, message);
+    }
+    public static void Error(String message, [CallerLineNumber] int line=0, [CallerFilePath] string file=null, [CallerMemberName] string member = null)
+    {
+        EnsureDomainRegistered();
+        eina_log_print(domain, Level.Error, file, member, line, message);
+    }
+    public static void Warning(String message, [CallerLineNumber] int line=0, [CallerFilePath] string file=null, [CallerMemberName] string member = null)
+    {
+        EnsureDomainRegistered();
+        eina_log_print(domain, Level.Warning, file, member, line, message);
+    }
+    public static void Info(String message, [CallerLineNumber] int line=0, [CallerFilePath] string file=null, [CallerMemberName] string member = null)
+    {
+        EnsureDomainRegistered();
+        eina_log_print(domain, Level.Info, file, member, line, message);
+    }
+    public static void Debug(String message, [CallerLineNumber] int line=0, [CallerFilePath] string file=null, [CallerMemberName] string member = null)
+    {
+        EnsureDomainRegistered();
+        eina_log_print(domain, Level.Debug, file, member, line, message);
+    }
+
+    public static void GlobalLevelSet(Level level)
+    {
+        eina_log_level_set(level);
+    }
+
+    public static Level GlobalLevelGet()
+    {
+        return eina_log_level_get();
+    }
+}
+}
diff --git a/src/bindings/mono/eina_mono/eina_slice.cs b/src/bindings/mono/eina_mono/eina_slice.cs
new file mode 100644 (file)
index 0000000..189e9a5
--- /dev/null
@@ -0,0 +1,85 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace eina {
+
+public interface ISliceBase
+{
+    UIntPtr Len {get;set;}
+    IntPtr Mem {get;set;}
+
+    int Length {get;set;}
+};
+
+[StructLayout(LayoutKind.Sequential)]
+public struct Slice : ISliceBase
+{
+    public UIntPtr Len {get;set;}
+    public IntPtr Mem {get;set;}
+
+    public int Length
+    {
+        get { return (int) Len; }
+        set { Len = (UIntPtr) value; }
+    }
+
+    public Slice(IntPtr mem, UIntPtr len)
+    {
+        Mem = mem;
+        Len = len;
+    }
+
+    public Slice PinnedDataSet(IntPtr mem, UIntPtr len)
+    {
+        Mem = mem;
+        Len = len;
+        return this;
+    }
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct Rw_Slice : ISliceBase
+{
+    public UIntPtr Len {get;set;}
+    public IntPtr Mem {get;set;}
+
+    public int Length
+    {
+        get { return (int) Len; }
+        set { Len = (UIntPtr) value; }
+    }
+
+    public Rw_Slice(IntPtr mem, UIntPtr len)
+    {
+        Mem = mem;
+        Len = len;
+    }
+
+    public Rw_Slice PinnedDataSet(IntPtr mem, UIntPtr len)
+    {
+        Mem = mem;
+        Len = len;
+        return this;
+    }
+
+    Slice ToSlice()
+    {
+        var r = new Slice();
+        r.Mem = Mem;
+        r.Len = Len;
+        return r;
+    }
+}
+
+}
+
+public static class Eina_SliceUtils
+{
+    public static byte[] GetBytes(this eina.ISliceBase slc)
+    {
+        var size = (int)(slc.Len);
+        byte[] mArray = new byte[size];
+        Marshal.Copy(slc.Mem, mArray, 0, size);
+        return mArray;
+    }
+}
diff --git a/src/bindings/mono/eina_mono/eina_stringshare.cs b/src/bindings/mono/eina_mono/eina_stringshare.cs
new file mode 100644 (file)
index 0000000..825103d
--- /dev/null
@@ -0,0 +1,18 @@
+
+using System;
+using System.Runtime.InteropServices;
+
+
+namespace eina {
+
+public class Stringshare {
+    [DllImport(efl.Libs.Eina)] public static extern System.IntPtr
+        eina_stringshare_add_length(string str, System.UInt32 slen);
+    [DllImport(efl.Libs.Eina)] public static extern System.IntPtr
+        eina_stringshare_add(string str);
+    [DllImport(efl.Libs.Eina)] public static extern void
+        eina_stringshare_del(System.IntPtr str);
+}
+
+}
+
diff --git a/src/bindings/mono/eina_mono/eina_value.cs b/src/bindings/mono/eina_mono/eina_value.cs
new file mode 100644 (file)
index 0000000..4ded15b
--- /dev/null
@@ -0,0 +1,1590 @@
+#define CODE_ANALYSIS
+
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+using System.Security.Permissions;
+using System.Security;
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.Serialization;
+
+using static eina.EinaNative.UnsafeNativeMethods;
+using static eina.TraitFunctions;
+
+
+namespace eina {
+
+namespace EinaNative {
+
+// Structs to be passed from/to C when dealing with containers and
+// optional values.
+[StructLayout(LayoutKind.Sequential)]
+struct Value_Array
+{
+    public IntPtr subtype;
+    public uint step;
+    public IntPtr subarray;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+struct Value_List
+{
+    public IntPtr subtype;
+    public IntPtr sublist;
+}
+
+[SuppressUnmanagedCodeSecurityAttribute]
+static internal class UnsafeNativeMethods {
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_convert(IntPtr handle, IntPtr convert);
+
+    // Wrapped and helper methods
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern int eina_value_sizeof();
+
+    [DllImport(efl.Libs.CustomExports, CharSet=CharSet.Ansi)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_set_wrapper(IntPtr handle, string value);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_set_wrapper(IntPtr handle, byte value);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_set_wrapper(IntPtr handle, sbyte value);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_set_wrapper(IntPtr handle, short value);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_set_wrapper(IntPtr handle, ushort value);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_set_wrapper(IntPtr handle, int value);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_set_wrapper(IntPtr handle, uint value);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_set_wrapper(IntPtr handle, long value);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_set_wrapper(IntPtr handle, ulong value);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_set_wrapper(IntPtr handle, float value);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_set_wrapper(IntPtr handle, double value);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_set_wrapper(IntPtr handle, IntPtr value);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_setup_wrapper(IntPtr handle, IntPtr type);
+
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern void eina_value_flush_wrapper(IntPtr handle);
+
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr eina_value_type_get_wrapper(IntPtr handle);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_get_wrapper(IntPtr handle, out IntPtr output);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_get_wrapper(IntPtr handle, out Value_List output);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_get_wrapper(IntPtr handle, out Value_Array output);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_get_wrapper(IntPtr handle, out byte output);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_get_wrapper(IntPtr handle, out sbyte output);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_get_wrapper(IntPtr handle, out short output);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_get_wrapper(IntPtr handle, out ushort output);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_get_wrapper(IntPtr handle, out int output);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_get_wrapper(IntPtr handle, out uint output);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_get_wrapper(IntPtr handle, out long output);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_get_wrapper(IntPtr handle, out ulong output);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_get_wrapper(IntPtr handle, out float output);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_get_wrapper(IntPtr handle, out double output);
+
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern int eina_value_compare_wrapper(IntPtr handle, IntPtr other);
+
+    [DllImport(efl.Libs.Eina, CharSet=CharSet.Ansi)]
+    internal static extern IntPtr eina_value_to_string(IntPtr handle); // We take ownership of the returned string.
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_array_setup_wrapper(IntPtr handle, IntPtr subtype, uint step);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_list_setup_wrapper(IntPtr handle, IntPtr subtype);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_array_append_wrapper(IntPtr handle, IntPtr data);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_list_append_wrapper(IntPtr handle, IntPtr data);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_array_get_wrapper(IntPtr handle, int index, out IntPtr output);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_list_get_wrapper(IntPtr handle, int index, out IntPtr output);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_array_set_wrapper(IntPtr handle, int index, IntPtr value);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_list_set_wrapper(IntPtr handle, int index, IntPtr value);
+
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr eina_value_array_subtype_get_wrapper(IntPtr handle);
+
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr eina_value_list_subtype_get_wrapper(IntPtr handle);
+
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern uint eina_value_array_count_wrapper(IntPtr handle);
+
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern uint eina_value_list_count_wrapper(IntPtr handle);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_empty_is_wrapper(IntPtr handle, [MarshalAsAttribute(UnmanagedType.U1)] out bool empty);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, ref byte value);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, ref sbyte value);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, ref short value);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, ref ushort value);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, ref int value);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, ref uint value);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, ref long value);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, ref ulong value);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, ref float value);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, ref double value);
+
+    [DllImport(efl.Libs.Eina, CharSet=CharSet.Ansi)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, ref string value);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pset(IntPtr handle, IntPtr subtype, IntPtr value);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_reset(IntPtr handle);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pget(IntPtr handle, out eina.EinaNative.Value_Array output);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pget(IntPtr handle, out eina.EinaNative.Value_List output);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pget(IntPtr handle, out IntPtr output);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pget(IntPtr handle, out byte output);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pget(IntPtr handle, out sbyte output);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pget(IntPtr handle, out short output);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pget(IntPtr handle, out ushort output);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pget(IntPtr handle, out int output);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pget(IntPtr handle, out uint output);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pget(IntPtr handle, out long output);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pget(IntPtr handle, out ulong output);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pget(IntPtr handle, out float output);
+
+    [DllImport(efl.Libs.Eina)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_optional_pget(IntPtr handle, out double output);
+
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr eina_value_optional_type_get_wrapper(IntPtr handle);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_pset_wrapper(IntPtr handle, ref eina.EinaNative.Value_Array ptr);
+
+    [DllImport(efl.Libs.CustomExports)]
+    [return: MarshalAsAttribute(UnmanagedType.U1)]
+    internal static extern bool eina_value_pset_wrapper(IntPtr handle, ref eina.EinaNative.Value_List ptr);
+
+    // Supported types
+
+    // 8 bits byte
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr type_byte();
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr type_sbyte();
+
+    // 16 bits short
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr type_short();
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr type_ushort();
+
+    // 32 bits ints
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr type_int32();
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr type_uint32();
+
+    // 64 bit longs
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr type_long();
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr type_ulong();
+
+    // In C# long and int 64 are synonyms, but in Eina Value they are separate types.
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr type_int64();
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr type_uint64();
+
+    // Floating point
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr type_float();
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr type_double();
+
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr type_string();
+
+    // Collections
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr type_array();
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr type_list();
+
+    // Optional
+    [DllImport(efl.Libs.CustomExports)]
+    internal static extern IntPtr type_optional();
+}
+}
+
+/// <summary>Struct for passing Values by value to Unmanaged functions.</summary>
+[StructLayout(LayoutKind.Sequential)]
+public struct Value_Native
+{
+    IntPtr type;
+    IntPtr value; // Atually an Eina_Value_Union, but it is padded to 8 bytes.
+}
+
+
+/// <summary>Exception for trying to access flushed values.</summary>
+[Serializable]
+public class ValueFlushedException : Exception
+{
+    /// <summary> Default constructor.</summary>
+    public ValueFlushedException() : base () { }
+    /// <summary> Most commonly used contructor.</summary>
+    public ValueFlushedException(string msg) : base(msg) { }
+    /// <summary> Wraps an inner exception.</summary>
+    public ValueFlushedException(string msg, Exception inner) : base(msg, inner) { }
+    /// <summary> Serializable constructor.</summary>
+    protected ValueFlushedException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+}
+
+/// <summary>Exception for failures when setting an container item.</summary>
+[Serializable]
+public class SetItemFailedException : Exception
+{
+    /// <summary> Default constructor.</summary>
+    public SetItemFailedException() : base () { }
+    /// <summary> Most commonly used contructor.</summary>
+    public SetItemFailedException(string msg) : base(msg) { }
+    /// <summary> Wraps an inner exception.</summary>
+    public SetItemFailedException(string msg, Exception inner) : base(msg, inner) { }
+    /// <summary> Serializable constructor.</summary>
+    protected SetItemFailedException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+}
+
+/// <summary>Exception for methods that must have been called on a container.</summary>
+[Serializable]
+public class InvalidValueTypeException: Exception
+{
+    /// <summary> Default constructor.</summary>
+    public InvalidValueTypeException() : base () { }
+    /// <summary> Most commonly used contructor.</summary>
+    public InvalidValueTypeException(string msg) : base(msg) { }
+    /// <summary> Wraps an inner exception.</summary>
+    public InvalidValueTypeException(string msg, Exception inner) : base(msg, inner) { }
+    /// <summary> Serializable constructor.</summary>
+    protected InvalidValueTypeException(SerializationInfo info, StreamingContext context) : base(info, context) { }
+}
+
+/// <summary>Internal enum to handle value ownership between managed and unmanaged code.</summary>
+public enum ValueOwnership {
+    /// <summary> The value is owned by the managed code. It'll free the handle on disposal.</summary>
+    Managed,
+    /// <summary> The value is owned by the unmanaged code. It won't be freed on disposal.</summary>
+    Unmanaged
+}
+
+/// <summary>Managed-side Enum to represent Eina_Value_Type constants</summary>
+public enum ValueType {
+    /// <summary>Signed 8 bit integer. Same as 'sbyte'</summary>
+    SByte,
+    /// <summary>Unsigned 8 bit integer. Same as 'byte'</summary>
+    Byte,
+    /// <summary>Signed 16 bit integer. Same as 'short'</summary>
+    Short,
+    /// <summary>Unsigned 16 bit integer. Same as 'ushort'</summary>
+    UShort,
+    /// <summary>Signed 32 bit integer. Same as 'int'</summary>
+    Int32,
+    /// <summary>Unsigned 32 bit integer. Same as 'uint'</summary>
+    UInt32,
+    /// <summary>Signed long integer. Same as 'long'</summary>
+    Long,
+    /// <summary>Unsigned long integer. Same as 'ulong'</summary>
+    ULong,
+    /// <summary>Signed 64 bit integer. Same as 'long'</summary>
+    Int64,
+    /// <summary>Unsigned 64 bit integer. Same as 'ulong'</summary>
+    UInt64,
+    /// <summary>4-byte float. Same as 'float'</summary>
+    Float,
+    /// <summary>8-byte double. Same as 'double'</summary>
+    Double,
+    /// <summary>Strings</summary>
+    String,
+    /// <summary>Array of Value items.</summary>
+    Array,
+    /// <summary>Linked list of Value items.</summary>
+    List,
+    /// <summary>Map of string keys to Value items.</summary>
+    Hash,
+    /// <summary>Optional (aka empty) values.</summary>
+    Optional,
+}
+
+static class ValueTypeMethods {
+    public static bool IsNumeric(this ValueType val)
+    {
+        switch (val) {
+            case ValueType.SByte:
+            case ValueType.Byte:
+            case ValueType.Short:
+            case ValueType.UShort:
+            case ValueType.Int32:
+            case ValueType.UInt32:
+            case ValueType.Long:
+            case ValueType.ULong:
+            case ValueType.Int64:
+            case ValueType.UInt64:
+            case ValueType.Float:
+            case ValueType.Double:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public static bool IsString(this ValueType val)
+    {
+        switch(val) {
+            case ValueType.String:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public static bool IsContainer(this ValueType val)
+    {
+        switch(val) {
+            case ValueType.Array:
+            case ValueType.List:
+            case ValueType.Hash:
+                return true;
+            default:
+                return false;
+        }
+    }
+
+    public static bool IsOptional(this ValueType val)
+    {
+        return val == ValueType.Optional;
+    }
+
+    /// <summary>Returns the Marshal.SizeOf for the given ValueType native structure.</summary>
+    public static int MarshalSizeOf(this ValueType val)
+    {
+        switch (val) {
+            case ValueType.Array:
+                return Marshal.SizeOf(typeof(EinaNative.Value_Array));
+            case ValueType.List:
+                return Marshal.SizeOf(typeof(EinaNative.Value_List));
+            default:
+                return 0;
+        }
+    }
+}
+static class ValueTypeBridge
+{
+    private static Dictionary<ValueType, IntPtr> ManagedToNative = new Dictionary<ValueType, IntPtr>();
+    private static Dictionary<IntPtr, ValueType> NativeToManaged = new Dictionary<IntPtr, ValueType>();
+    private static bool TypesLoaded; // CLR defaults to false;
+
+    public static ValueType GetManaged(IntPtr native)
+    {
+        if (!TypesLoaded)
+            LoadTypes();
+
+        return NativeToManaged[native];
+    }
+
+    public static IntPtr GetNative(ValueType valueType)
+    {
+        if (!TypesLoaded)
+            LoadTypes();
+
+        return ManagedToNative[valueType];
+    }
+
+    private static void LoadTypes()
+    {
+        eina.Config.Init(); // Make sure eina is initialized.
+
+        ManagedToNative.Add(ValueType.SByte, type_sbyte());
+        NativeToManaged.Add(type_sbyte(), ValueType.SByte);
+
+        ManagedToNative.Add(ValueType.Byte, type_byte());
+        NativeToManaged.Add(type_byte(), ValueType.Byte);
+
+        ManagedToNative.Add(ValueType.Short, type_short());
+        NativeToManaged.Add(type_short(), ValueType.Short);
+
+        ManagedToNative.Add(ValueType.UShort, type_ushort());
+        NativeToManaged.Add(type_ushort(), ValueType.UShort);
+
+        ManagedToNative.Add(ValueType.Int32, type_int32());
+        NativeToManaged.Add(type_int32(), ValueType.Int32);
+
+        ManagedToNative.Add(ValueType.UInt32, type_uint32());
+        NativeToManaged.Add(type_uint32(), ValueType.UInt32);
+
+        ManagedToNative.Add(ValueType.Long, type_long());
+        NativeToManaged.Add(type_long(), ValueType.Long);
+
+        ManagedToNative.Add(ValueType.ULong, type_ulong());
+        NativeToManaged.Add(type_ulong(), ValueType.ULong);
+
+        ManagedToNative.Add(ValueType.Int64, type_int64());
+        NativeToManaged.Add(type_int64(), ValueType.Int64);
+
+        ManagedToNative.Add(ValueType.UInt64, type_uint64());
+        NativeToManaged.Add(type_uint64(), ValueType.UInt64);
+
+        ManagedToNative.Add(ValueType.Float, type_float());
+        NativeToManaged.Add(type_float(), ValueType.Float);
+
+        ManagedToNative.Add(ValueType.Double, type_double());
+        NativeToManaged.Add(type_double(), ValueType.Double);
+
+        ManagedToNative.Add(ValueType.String, type_string());
+        NativeToManaged.Add(type_string(), ValueType.String);
+
+        ManagedToNative.Add(ValueType.Array, type_array());
+        NativeToManaged.Add(type_array(), ValueType.Array);
+
+        ManagedToNative.Add(ValueType.List, type_list());
+        NativeToManaged.Add(type_list(), ValueType.List);
+
+        ManagedToNative.Add(ValueType.Optional, type_optional());
+        NativeToManaged.Add(type_optional(), ValueType.Optional);
+
+        TypesLoaded = true;
+    }
+}
+
+/// <summary>Wrapper around Eina_Value generic storage.
+///
+/// <para>Eina_Value is EFL's main workhorse to deal with storing generic data in
+/// an uniform way.</para>
+///
+/// <para>It comes with predefined types for numbers, strings, array, list, hash,
+/// blob and structs. It is able to convert between data types, including
+/// to string.</para>
+/// </summary>
+public class Value : IDisposable, IComparable<Value>, IEquatable<Value>
+{
+
+    // Unmanaged type - Managed type mapping
+    // Ok EINA_VALUE_TYPE_UCHAR: unsigned char -- byte
+    // Ok EINA_VALUE_TYPE_USHORT: unsigned short -- ushort
+    // Ok EINA_VALUE_TYPE_UINT: unsigned int -- uint
+    // Ok EINA_VALUE_TYPE_ULONG: unsigned long -- ulong
+    // Ok EINA_VALUE_TYPE_UINT64: uint64_t -- ulong
+    // Ok EINA_VALUE_TYPE_CHAR: char -- sbyte
+    // Ok EINA_VALUE_TYPE_SHORT: short -- short
+    // Ok EINA_VALUE_TYPE_INT: int -- int
+    // Ok EINA_VALUE_TYPE_LONG: long -- long
+    // OK EINA_VALUE_TYPE_INT64: int64_t -- long
+    // Ok EINA_VALUE_TYPE_FLOAT: float -- float
+    // Ok EINA_VALUE_TYPE_DOUBLE: double -- double
+    // EINA_VALUE_TYPE_STRINGSHARE: const char * -- string
+    // Ok EINA_VALUE_TYPE_STRING: const char * -- string
+    // Ok EINA_VALUE_TYPE_ARRAY: Eina_Value_Array -- eina.Array?
+    // Ok EINA_VALUE_TYPE_LIST: Eina_Value_List -- eina.List?
+    // EINA_VALUE_TYPE_HASH: Eina_Value_Hash -- eina.Hash?
+    // EINA_VALUE_TYPE_TIMEVAL: struct timeval -- FIXME
+    // EINA_VALUE_TYPE_BLOB: Eina_Value_Blob -- FIXME
+    // EINA_VALUE_TYPE_STRUCT: Eina_Value_Struct -- FIXME
+
+
+    public IntPtr Handle { get; protected set;}
+    public ValueOwnership Ownership { get; protected set;}
+    private bool Disposed;
+    public bool Flushed { get; protected set;}
+    public bool Optional {
+        get {
+            return GetValueType() == eina.ValueType.Optional;
+        }
+        /* protected set {
+            // Should we expose this?
+            // Something like {
+            //    flush(handle)/free(handle)
+            //    handle = eina_value_optional_empty_new()
+            // }
+         } */
+    }
+    public bool Empty {
+        get {
+            OptionalSanityChecks();
+            bool empty;
+            if (!eina_value_optional_empty_is_wrapper(this.Handle, out empty))
+                throw new System.InvalidOperationException("Couldn't get the empty information");
+            else
+                return empty;
+        }
+    }
+
+    // Constructor to be used by the "FromContainerDesc" methods.
+    private Value() {
+        this.Handle = MemoryNative.Alloc(eina_value_sizeof());
+        this.Ownership = ValueOwnership.Managed;
+    }
+
+    internal Value(IntPtr handle, ValueOwnership ownership=ValueOwnership.Managed) {
+        this.Handle = handle;
+        this.Ownership = ownership;
+    }
+
+    /// <summary>Creates a new value storage for values of type 'type'.</summary>
+    public Value(ValueType type)
+    {
+        if (type.IsContainer())
+            throw new ArgumentException("To use container types you must provide a subtype");
+        this.Handle = MemoryNative.Alloc(eina_value_sizeof());
+        this.Ownership = ValueOwnership.Managed;
+        Setup(type);
+    }
+
+    /// <summary>Constructor for container values, like Array, Hash.</summary>
+    public Value(ValueType containerType, ValueType subtype, uint step=0)
+    {
+        if (!containerType.IsContainer())
+            throw new ArgumentException("First type must be a container type.");
+
+        this.Handle = MemoryNative.Alloc(eina_value_sizeof());
+        this.Ownership = ValueOwnership.Managed;
+
+        Setup(containerType, subtype, step);
+    }
+
+    /// <summary>Constructor to build value from Values_Natives passed by value from C
+    public Value(Value_Native value)
+    {
+        this.Handle = MemoryNative.Alloc(Marshal.SizeOf(typeof(Value_Native)));
+        try {
+            Marshal.StructureToPtr(value, this.Handle, false);
+        } catch {
+            MemoryNative.Free(this.Handle);
+            throw;
+        }
+        this.Ownership = ValueOwnership.Managed;
+    }
+
+    /// <summary>Implicit conversion from managed value to native struct representation
+    public static implicit operator Value_Native(Value v)
+    {
+        return v.GetNative();
+    }
+
+    /// <summary>
+    public static implicit operator Value(Value_Native v)
+    {
+        return new Value(v);
+    }
+
+    /// <summary>Creates an Value instance from a given array description.</summary>
+    private static Value FromArrayDesc(eina.EinaNative.Value_Array arrayDesc)
+    {
+        Value value = new Value();
+        value.Setup(ValueType.Array, ValueType.String); // Placeholder values to be overwritten by the following pset call.
+
+        eina_value_pset_wrapper(value.Handle, ref arrayDesc);
+        return value;
+    }
+
+    /// <summary>Creates an Value instance from a given array description.</summary>
+    private static Value FromListDesc(eina.EinaNative.Value_List listDesc)
+    {
+        Value value = new Value();
+        value.Setup(ValueType.List, ValueType.String); // Placeholder values to be overwritten by the following pset call.
+
+        eina_value_pset_wrapper(value.Handle, ref listDesc);
+        return value;
+    }
+
+    /// <summary>Releases the ownership of the underlying value to C.</summary>
+    public void ReleaseOwnership()
+    {
+        this.Ownership = ValueOwnership.Unmanaged;
+    }
+
+    /// <summary>Takes the ownership of the underlying value to the Managed runtime.</summary>
+    public void TakeOwnership()
+    {
+        this.Ownership = ValueOwnership.Managed;
+    }
+
+    /// <summary>Public method to explicitly free the wrapped eina value.</summary>
+    public void Dispose()
+    {
+        Dispose(true);
+        GC.SuppressFinalize(this);
+    }
+
+    /// <summary>Actually free the wrapped eina value. Can be called from Dispose() or through the GC.</summary>
+    protected virtual void Dispose(bool disposing)
+    {
+        if (this.Ownership == ValueOwnership.Unmanaged) {
+            Disposed = true;
+            return;
+        }
+
+        if (!Disposed && (Handle != IntPtr.Zero)) {
+            if (!Flushed)
+                eina_value_flush_wrapper(this.Handle);
+
+            MemoryNative.Free(this.Handle);
+        }
+        Disposed = true;
+    }
+
+    /// <summary>Finalizer to be called from the Garbage Collector.</summary>
+    ~Value()
+    {
+        Dispose(false);
+    }
+
+    /// <summary>Returns the native handle wrapped by this object.</summary>
+    public IntPtr NativeHandle()
+    {
+        if (Disposed)
+            throw new ObjectDisposedException(base.GetType().Name);
+        return this.Handle;
+    }
+
+    /// <summary>Converts this storage to type 'type'</summary>
+    public bool Setup(ValueType type)
+    {
+        if (Disposed)
+            throw new ObjectDisposedException(base.GetType().Name);
+
+        if (type.IsContainer())
+            throw new ArgumentException("To setup a container you must provide a subtype.");
+
+        bool ret = eina_value_setup_wrapper(this.Handle, ValueTypeBridge.GetNative(type));
+        if (ret)
+            Flushed = false;
+        return ret;
+    }
+
+    public bool Setup(ValueType containerType, ValueType subtype, uint step=0) {
+        IntPtr native_subtype = ValueTypeBridge.GetNative(subtype);
+        bool ret = false;
+        switch (containerType) {
+            case ValueType.Array:
+                ret = eina_value_array_setup_wrapper(this.Handle, native_subtype, step);
+                break;
+            case ValueType.List:
+                ret = eina_value_list_setup_wrapper(this.Handle, native_subtype);
+                break;
+        }
+
+        if (ret)
+            Flushed = false;
+
+        return ret;
+    }
+
+    private void SanityChecks()
+    {
+        if (Disposed)
+            throw new ObjectDisposedException(GetType().Name);
+        if (Flushed)
+            throw new ValueFlushedException("Trying to use value that has been flushed. Setup it again.");
+    }
+
+    private void ContainerSanityChecks(int targetIndex=-1)
+    {
+        SanityChecks();
+        uint size = 0;
+        ValueType type = GetValueType();
+
+        if (!type.IsContainer())
+                throw new InvalidValueTypeException("Value type must be a container");
+
+        if (targetIndex == -1)  // Some methods (e.g. append) don't care about size
+            return;
+
+        switch (type) {
+            case ValueType.Array:
+                size = eina_value_array_count_wrapper(this.Handle);
+                break;
+            case ValueType.List:
+                size = eina_value_list_count_wrapper(this.Handle);
+                break;
+        }
+
+        if (targetIndex >= size)
+                throw new System.ArgumentOutOfRangeException(
+                        $"Index {targetIndex} is larger than max array index {size-1}");
+    }
+
+    private void OptionalSanityChecks()
+    {
+        SanityChecks();
+        ValueType type = GetValueType();
+
+        if (!type.IsOptional())
+            throw new InvalidValueTypeException("Value is not an Optional one");
+    }
+
+    /// <summary>Releases the memory stored by this value. It can be reused by calling setup again.
+    /// </summary>
+    public void Flush()
+    {
+        if (Disposed)
+            throw new ObjectDisposedException(GetType().Name);
+        eina_value_flush_wrapper(this.Handle);
+        Flushed = true;
+    }
+
+    /// <summary>Get a Value_Native struct with the *value* pointed by this eina.Value.</summary>
+    public Value_Native GetNative()
+    {
+        Value_Native value = (Value_Native)Marshal.PtrToStructure(this.Handle, typeof(Value_Native));
+        return value;
+    }
+
+    public bool Set(byte value)
+    {
+        SanityChecks();
+
+        if (this.Optional)
+            return eina_value_optional_pset(this.Handle,
+                                            ValueTypeBridge.GetNative(ValueType.Byte),
+                                            ref value);
+
+        if (!GetValueType().IsNumeric())
+            throw (new ArgumentException(
+                        "Trying to set numeric value on a non-numeric eina.Value"));
+        return eina_value_set_wrapper(this.Handle, value);
+    }
+
+    public bool Set(sbyte value)
+    {
+        SanityChecks();
+
+        if (this.Optional)
+            return eina_value_optional_pset(this.Handle,
+                                            ValueTypeBridge.GetNative(ValueType.SByte),
+                                            ref value);
+
+        if (!GetValueType().IsNumeric())
+            throw (new ArgumentException(
+                        "Trying to set numeric value on a non-numeric eina.Value"));
+        return eina_value_set_wrapper(this.Handle, value);
+    }
+
+    public bool Set(short value)
+    {
+        SanityChecks();
+
+        if (this.Optional)
+            return eina_value_optional_pset(this.Handle,
+                                            ValueTypeBridge.GetNative(ValueType.Short),
+                                            ref value);
+
+        if (!GetValueType().IsNumeric())
+            throw (new ArgumentException(
+                        "Trying to set numeric value on a non-numeric eina.Value"));
+        return eina_value_set_wrapper(this.Handle, value);
+    }
+
+    public bool Set(ushort value)
+    {
+        SanityChecks();
+
+        if (this.Optional)
+            return eina_value_optional_pset(this.Handle,
+                                            ValueTypeBridge.GetNative(ValueType.UShort),
+                                            ref value);
+
+        if (!GetValueType().IsNumeric())
+            throw (new ArgumentException(
+                        "Trying to set numeric value on a non-numeric eina.Value"));
+        return eina_value_set_wrapper(this.Handle, value);
+    }
+
+    /// <summary>Stores the given uint value.</summary>
+    public bool Set(uint value)
+    {
+        SanityChecks();
+
+        if (this.Optional)
+            return eina_value_optional_pset(this.Handle,
+                                            ValueTypeBridge.GetNative(ValueType.UInt32),
+                                            ref value);
+
+        if (!GetValueType().IsNumeric())
+            throw (new ArgumentException(
+                        "Trying to set numeric value on a non-numeric eina.Value"));
+        return eina_value_set_wrapper(this.Handle, value);
+    }
+
+    /// <summary>Stores the given int value.</summary>
+    public bool Set(int value)
+    {
+        SanityChecks();
+
+        if (this.Optional)
+            return eina_value_optional_pset(this.Handle,
+                                            ValueTypeBridge.GetNative(ValueType.Int32),
+                                            ref value);
+
+        if (!GetValueType().IsNumeric())
+            throw (new ArgumentException(
+                        "Trying to set numeric value on a non-numeric eina.Value"));
+        return eina_value_set_wrapper(this.Handle, value);
+    }
+
+    /// <summary>Stores the given ulong value.</summary>
+    public bool Set(ulong value)
+    {
+        SanityChecks();
+
+        if (this.Optional)
+            return eina_value_optional_pset(this.Handle,
+                                            ValueTypeBridge.GetNative(ValueType.ULong),
+                                            ref value);
+
+        if (!GetValueType().IsNumeric())
+            throw (new ArgumentException(
+                        "Trying to set numeric value on a non-numeric eina.Value"));
+        return eina_value_set_wrapper(this.Handle, value);
+    }
+
+    /// <summary>Stores the given int value.</summary>
+    public bool Set(long value)
+    {
+        SanityChecks();
+
+        if (this.Optional)
+            return eina_value_optional_pset(this.Handle,
+                                            ValueTypeBridge.GetNative(ValueType.Long),
+                                            ref value);
+
+        if (!GetValueType().IsNumeric())
+            throw (new ArgumentException(
+                        "Trying to set numeric value on a non-numeric eina.Value"));
+        return eina_value_set_wrapper(this.Handle, value);
+    }
+
+    /// <summary>Stores the given int value.</summary>
+    public bool Set(float value)
+    {
+        SanityChecks();
+
+        if (this.Optional)
+            return eina_value_optional_pset(this.Handle,
+                                            ValueTypeBridge.GetNative(ValueType.Float),
+                                            ref value);
+
+        if (!GetValueType().IsNumeric())
+            throw (new ArgumentException(
+                        "Trying to set numeric value on a non-numeric eina.Value"));
+
+        Console.WriteLine("Wrapper Set({0})", value);
+        return eina_value_set_wrapper(this.Handle, value);
+    }
+
+    /// <summary>Stores the given int value.</summary>
+    public bool Set(double value)
+    {
+        SanityChecks();
+
+        if (this.Optional)
+            return eina_value_optional_pset(this.Handle,
+                                            ValueTypeBridge.GetNative(ValueType.Double),
+                                            ref value);
+
+        if (!GetValueType().IsNumeric())
+            throw (new ArgumentException(
+                        "Trying to set numeric value on a non-numeric eina.Value"));
+        return eina_value_set_wrapper(this.Handle, value);
+    }
+
+    /// <summary>Stores the given string value.</summary>
+    public bool Set(string value)
+    {
+        SanityChecks();
+
+        if (this.Optional)
+            return eina_value_optional_pset(this.Handle,
+                                            ValueTypeBridge.GetNative(ValueType.String),
+                                            ref value);
+
+        if (!GetValueType().IsString())
+            throw (new ArgumentException(
+                        "Trying to set non-string value on a string eina.Value"));
+        // No need to worry about ownership as eina_value_set will copy the passed string.
+        return eina_value_set_wrapper(this.Handle, value);
+    }
+
+    /// <summary>Stores the given value into this value. The target value must be an optional.</summary>
+    public bool Set(Value value)
+    {
+        OptionalSanityChecks();
+        ValueType subtype = value.GetValueType();
+
+        IntPtr ptr_val = MemoryNative.Alloc(subtype.MarshalSizeOf());
+        IntPtr native_type = ValueTypeBridge.GetNative(subtype);
+
+        try {
+            switch (subtype) {
+                // PSet on Container types require an Eina_Value_<Container>, which is the structure
+                // that contains subtype, etc.
+                case ValueType.Array:
+                    EinaNative.Value_Array value_array;
+                    if (!eina_value_get_wrapper(value.Handle, out value_array))
+                        return false;
+                    Marshal.StructureToPtr(value_array, ptr_val, false);
+                    break;
+                case ValueType.List:
+                    EinaNative.Value_List value_list;
+                    if (!eina_value_get_wrapper(value.Handle, out value_list))
+                        return false;
+                    Marshal.StructureToPtr(value_list, ptr_val, false);
+                    break;
+                default:
+                    throw new InvalidValueTypeException("Only containers can be passed as raw eina.Values");
+            }
+
+            return eina_value_optional_pset(this.Handle, native_type, ptr_val);
+        } finally {
+            MemoryNative.Free(ptr_val);
+        }
+    }
+
+    /// <summary>Gets the currently stored value as a byte.</summary>
+    public bool Get(out byte value)
+    {
+        SanityChecks();
+        if (this.Optional)
+            return eina_value_optional_pget(this.Handle, out value);
+        else
+            return eina_value_get_wrapper(this.Handle, out value);
+    }
+
+    /// <summary>Gets the currently stored value as a sbyte.</summary>
+    public bool Get(out sbyte value)
+    {
+        SanityChecks();
+        if (this.Optional)
+            return eina_value_optional_pget(this.Handle, out value);
+        else
+            return eina_value_get_wrapper(this.Handle, out value);
+    }
+
+    /// <summary>Gets the currently stored value as a short.</summary>
+    public bool Get(out short value)
+    {
+        SanityChecks();
+        if (this.Optional)
+            return eina_value_optional_pget(this.Handle, out value);
+        else
+            return eina_value_get_wrapper(this.Handle, out value);
+    }
+
+    /// <summary>Gets the currently stored value as an ushort.</summary>
+    public bool Get(out ushort value)
+    {
+        SanityChecks();
+        if (this.Optional)
+            return eina_value_optional_pget(this.Handle, out value);
+        else
+            return eina_value_get_wrapper(this.Handle, out value);
+    }
+
+    /// <summary>Gets the currently stored value as an int.</summary>
+    public bool Get(out int value)
+    {
+        SanityChecks();
+        if (this.Optional)
+            return eina_value_optional_pget(this.Handle, out value);
+        else
+            return eina_value_get_wrapper(this.Handle, out value);
+    }
+
+    /// <summary>Gets the currently stored value as an uint.</summary>
+    public bool Get(out uint value)
+    {
+        SanityChecks();
+        if (this.Optional)
+            return eina_value_optional_pget(this.Handle, out value);
+        else
+            return eina_value_get_wrapper(this.Handle, out value);
+    }
+
+    /// <summary>Gets the currently stored value as a long.</summary>
+    public bool Get(out long value)
+    {
+        SanityChecks();
+        if (this.Optional)
+            return eina_value_optional_pget(this.Handle, out value);
+        else
+            return eina_value_get_wrapper(this.Handle, out value);
+    }
+
+    /// <summary>Gets the currently stored value as an ulong.</summary>
+    public bool Get(out ulong value)
+    {
+        SanityChecks();
+        if (this.Optional)
+            return eina_value_optional_pget(this.Handle, out value);
+        else
+            return eina_value_get_wrapper(this.Handle, out value);
+    }
+
+    /// <summary>Gets the currently stored value as a float.</summary>
+    public bool Get(out float value)
+    {
+        SanityChecks();
+        if (this.Optional)
+            return eina_value_optional_pget(this.Handle, out value);
+        else
+            return eina_value_get_wrapper(this.Handle, out value);
+    }
+
+    /// <summary>Gets the currently stored value as a double.</summary>
+    public bool Get(out double value)
+    {
+        SanityChecks();
+        if (this.Optional)
+            return eina_value_optional_pget(this.Handle, out value);
+        else
+            return eina_value_get_wrapper(this.Handle, out value);
+    }
+
+    /// <summary>Gets the currently stored value as a string.</summary>
+    public bool Get(out string value)
+    {
+        SanityChecks();
+        IntPtr output = IntPtr.Zero;
+        if (this.Optional) {
+            if (!eina_value_optional_pget(this.Handle, out output)) {
+                value = String.Empty;
+                return false;
+            }
+        } else if (!eina_value_get_wrapper(this.Handle, out output)) {
+            value = String.Empty;
+            return false;
+        }
+        value = StringConversion.NativeUtf8ToManagedString(output);
+        return true;
+    }
+
+    /// <summary>Gets the currently stored value as an complex (e.g. container) eina.Value.</summary>
+    public bool Get(out Value value)
+    {
+        SanityChecks();
+        value = null;
+
+        if (!this.Optional)
+            throw new InvalidValueTypeException("Values can only be retreived");
+
+        IntPtr nativeType = eina_value_optional_type_get_wrapper(this.Handle);
+        ValueType managedType = ValueTypeBridge.GetManaged(nativeType);
+
+        switch (managedType) {
+            case ValueType.Array:
+                eina.EinaNative.Value_Array array_desc;
+
+                if (!eina_value_optional_pget(this.Handle, out array_desc))
+                    return false;
+                value = Value.FromArrayDesc(array_desc);
+                break;
+            case ValueType.List:
+                eina.EinaNative.Value_List list_desc;
+
+                if (!eina_value_optional_pget(this.Handle, out list_desc))
+                    return false;
+                value = Value.FromListDesc(list_desc);
+                break;
+        }
+
+        return true;
+    }
+
+    /// <summary>Gets the 'Type' this value is currently configured to store.</summary>
+    public ValueType GetValueType()
+    {
+        if (Disposed)
+            throw new ObjectDisposedException(base.GetType().Name);
+        IntPtr native_type = eina_value_type_get_wrapper(this.Handle);
+        return ValueTypeBridge.GetManaged(native_type);
+    }
+
+    /// <summary>Converts the value on this storage to the type of 'target' and stores
+    /// the result in 'target'.</summary>
+    public bool ConvertTo(Value target)
+    {
+        if (target == null)
+            return false;
+
+        SanityChecks();
+
+        return eina_value_convert(this.Handle, target.Handle);
+    }
+
+    /// <summary>Compare two eina values.</summary>
+    public int CompareTo(Value other)
+    {
+        if (other == null)
+            return 1;
+        SanityChecks();
+        other.SanityChecks();
+        return eina_value_compare_wrapper(this.Handle, other.Handle);
+    }
+
+    public int Compare(Value other)
+    {
+        return this.CompareTo(other);
+    }
+
+    public override bool Equals(object obj)
+    {
+        if (obj == null)
+            return false;
+
+        Value v = obj as Value;
+        if (v == null)
+            return false;
+
+        return this.Equals(v);
+    }
+
+    public bool Equals(Value other)
+    {
+        try {
+            return this.CompareTo(other) == 0;
+        } catch (ObjectDisposedException) {
+            return false;
+        } catch (ValueFlushedException) {
+            return false;
+        }
+    }
+
+    public override int GetHashCode()
+    {
+        return this.Handle.ToInt32();
+    }
+
+    public static bool operator==(Value x, Value y)
+    {
+        if (object.ReferenceEquals(x, null))
+            return object.ReferenceEquals(y, null);
+
+        return x.Equals(y);
+    }
+
+    public static bool operator!=(Value x, Value y)
+    {
+        if (object.ReferenceEquals(x, null))
+            return !object.ReferenceEquals(y, null);
+        return !x.Equals(y);
+    }
+
+    public static bool operator>(Value x, Value y)
+    {
+        if (object.ReferenceEquals(x, null) || object.ReferenceEquals(y, null))
+            return false;
+        return x.CompareTo(y) > 0;
+    }
+
+    public static bool operator<(Value x, Value y)
+    {
+        if (object.ReferenceEquals(x, null) || object.ReferenceEquals(y, null))
+            return false;
+        return x.CompareTo(y) < 0;
+    }
+
+
+    /// <summary>Converts value to string.</summary>
+    public override String ToString()
+    {
+        SanityChecks();
+        IntPtr ptr = eina_value_to_string(this.Handle);
+        String str = Marshal.PtrToStringAnsi(ptr);
+        MemoryNative.Free(ptr);
+        return str;
+    }
+
+    /// <summary>Empties an optional eina.Value, freeing what was previously contained.</summary>
+    public bool Reset()
+    {
+        OptionalSanityChecks();
+        return eina_value_optional_reset(this.Handle);
+    }
+
+    // Container methods methods
+    public int Count() {
+        ContainerSanityChecks();
+        switch(GetValueType()) {
+            case ValueType.Array:
+                return (int)eina_value_array_count_wrapper(this.Handle);
+            case ValueType.List:
+                return (int)eina_value_list_count_wrapper(this.Handle);
+        }
+        return -1;
+    }
+    public bool Append(object o) {
+        ContainerSanityChecks();
+        using (DisposableIntPtr marshalled_value = MarshalValue(o)) {
+            switch (GetValueType()) {
+                case ValueType.Array:
+                    return eina_value_array_append_wrapper(this.Handle, marshalled_value.Handle);
+                case ValueType.List:
+                    return eina_value_list_append_wrapper(this.Handle, marshalled_value.Handle);
+            }
+        }
+        return false;
+    }
+
+    public object this[int i]
+    {
+        get {
+            ContainerSanityChecks(i);
+
+            IntPtr output = IntPtr.Zero;
+            switch (GetValueType()) {
+                case ValueType.Array:
+                    if (!eina_value_array_get_wrapper(this.Handle, i, out output))
+                        return null;
+                    break;
+                case ValueType.List:
+                    if (!eina_value_list_get_wrapper(this.Handle, i, out output))
+                        return null;
+                    break;
+            }
+            return UnMarshalPtr(output);
+        }
+        set {
+            ContainerSanityChecks(i);
+
+            switch (GetValueType()) {
+                case ValueType.Array:
+                    ArraySet(i, value);
+                    break;
+                case ValueType.List:
+                    ListSet(i, value);
+                    break;
+            }
+        }
+    }
+
+    private void ArraySet(int i, object value) {
+        using (DisposableIntPtr marshalled_value = MarshalValue(value))
+        {
+            if (!eina_value_array_set_wrapper(this.Handle, i,
+                                              marshalled_value.Handle)) {
+                throw new SetItemFailedException($"Failed to set item at index {i}");
+            }
+        }
+    }
+
+    private void ListSet(int i, object value) {
+        using (DisposableIntPtr marshalled_value = MarshalValue(value))
+        {
+            if (!eina_value_list_set_wrapper(this.Handle, i,
+                                             marshalled_value.Handle)) {
+                throw new SetItemFailedException($"Failed to set item at index {i}");
+            }
+        }
+    }
+
+    public ValueType GetValueSubType()
+    {
+        ContainerSanityChecks();
+
+        IntPtr native_subtype = IntPtr.Zero;
+
+        switch (GetValueType()) {
+            case ValueType.Array:
+                native_subtype = eina_value_array_subtype_get_wrapper(this.Handle);
+                break;
+            case ValueType.List:
+                native_subtype = eina_value_list_subtype_get_wrapper(this.Handle);
+                break;
+        }
+        return ValueTypeBridge.GetManaged(native_subtype);
+    }
+
+    private DisposableIntPtr MarshalValue(object value)
+    {
+        IntPtr ret = IntPtr.Zero;
+        bool shouldFree = false;
+        switch(GetValueSubType()) {
+            case ValueType.Int32:
+                {
+                    int x = Convert.ToInt32(value);
+                    ret = new IntPtr(x);
+                }
+                break;
+            case ValueType.UInt32:
+                {
+                    uint x = Convert.ToUInt32(value);
+                    ret = new IntPtr((int)x);
+                }
+                break;
+            case ValueType.String:
+                {
+                    string x = value as string;
+                    if (x == null)
+                        ret = IntPtr.Zero;
+                    else {
+                        ret = StringConversion.ManagedStringToNativeUtf8Alloc(x);
+                        shouldFree = true;
+                    }
+                }
+                break;
+        }
+
+        return new DisposableIntPtr(ret, shouldFree);
+    }
+
+    private object UnMarshalPtr(IntPtr data)
+    {
+        switch(GetValueSubType()) {
+            case ValueType.Int32:
+                return Convert.ToInt32(data.ToInt32());
+            case ValueType.UInt32:
+                return Convert.ToUInt32(data.ToInt32());
+            case ValueType.String:
+                return StringConversion.NativeUtf8ToManagedString(data);
+            default:
+                return null;
+        }
+    }
+
+}
+
+/// <summary> Custom marshaler to convert value pointers to managed values and back,
+/// without changing ownership.</summary>
+public class ValueMarshaler : ICustomMarshaler {
+
+    /// <summary>Creates a managed value from a C pointer, whitout taking ownership of it.</summary>
+    public object MarshalNativeToManaged(IntPtr pNativeData) {
+        return new Value(pNativeData, ValueOwnership.Unmanaged);
+    }
+
+    /// <summary>Retrieves the C pointer from a given managed value,
+    /// keeping the managed ownership.</summary>
+    public IntPtr MarshalManagedToNative(object managedObj) {
+        try {
+            Value v = (Value)managedObj;
+            return v.Handle;
+        } catch (InvalidCastException) {
+            return IntPtr.Zero;
+        }
+    }
+
+    public void CleanUpNativeData(IntPtr pNativeData) {
+    }
+
+    public void CleanUpManagedData(object managedObj) {
+    }
+
+    public int GetNativeDataSize() {
+        return -1;
+    }
+
+    public static ICustomMarshaler GetInstance(string cookie) {
+        if (marshaler == null) {
+            marshaler = new ValueMarshaler();
+        }
+        return marshaler;
+    }
+    static private ValueMarshaler marshaler;
+}
+
+/// <summary> Custom marshaler to convert value pointers to managed values and back,
+/// also transferring the ownership to the other side.</summary>
+public class ValueMarshalerOwn : ICustomMarshaler {
+    /// <summary>Creates a managed value from a C pointer, taking the ownership.</summary>
+    public object MarshalNativeToManaged(IntPtr pNativeData) {
+        return new Value(pNativeData, ValueOwnership.Managed);
+    }
+
+    /// <summary>Retrieves the C pointer from a given managed value,
+    /// transferring the ownership to the unmanaged side, which should release it
+    /// when not needed. </summary>
+    public IntPtr MarshalManagedToNative(object managedObj) {
+        try {
+            Value v = (Value)managedObj;
+            v.ReleaseOwnership();
+            return v.Handle;
+        } catch (InvalidCastException) {
+            return IntPtr.Zero;
+        }
+    }
+
+    public void CleanUpNativeData(IntPtr pNativeData) {
+    }
+
+    public void CleanUpManagedData(object managedObj) {
+    }
+
+    public int GetNativeDataSize() {
+        return -1;
+    }
+
+    public static ICustomMarshaler GetInstance(string cookie) {
+        if (marshaler == null) {
+            marshaler = new ValueMarshalerOwn();
+        }
+        return marshaler;
+    }
+    static private ValueMarshalerOwn marshaler;
+}
+}
diff --git a/src/bindings/mono/eldbus_mono/eldbus_common.cs b/src/bindings/mono/eldbus_mono/eldbus_common.cs
new file mode 100644 (file)
index 0000000..9513858
--- /dev/null
@@ -0,0 +1,561 @@
+using System;
+using System.Runtime.InteropServices;
+
+using static eldbus.EldbusMessageNativeFunctions;
+
+namespace eldbus {
+
+public static class Timeout
+{
+    public static int Infinite = 0x7fffffff;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct ObjectPath
+{
+    public string value;
+
+    public ObjectPath(string str)
+    {
+        value = str;
+    }
+
+    public static implicit operator ObjectPath(string str)
+    {
+        return new ObjectPath(str);
+    }
+    public static implicit operator string(ObjectPath path)
+    {
+        return path.value;
+    }
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct SignatureString
+{
+    public string value;
+
+    public SignatureString(string str)
+    {
+        value = str;
+    }
+
+    public static implicit operator SignatureString(string str)
+    {
+        return new SignatureString(str);
+    }
+    public static implicit operator string(SignatureString sig)
+    {
+        return sig.value;
+    }
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct UnixFd
+{
+    public Int32 value;
+
+    public UnixFd(Int32 fd)
+    {
+        value = fd;
+    }
+
+    public static implicit operator UnixFd(Int32 fd)
+    {
+        return new UnixFd(fd);
+    }
+    public static implicit operator Int32(UnixFd unix_fd)
+    {
+        return unix_fd.value;
+    }
+}
+
+
+public static class Argument
+{
+    public class ByteType       { public const char Code = 'y'; public const string Signature = "y"; }
+    public class BooleanType    { public const char Code = 'b'; public const string Signature = "b"; }
+    public class Int16Type      { public const char Code = 'n'; public const string Signature = "n"; }
+    public class UInt16Type     { public const char Code = 'q'; public const string Signature = "q"; }
+    public class Int32Type      { public const char Code = 'i'; public const string Signature = "i"; }
+    public class UInt32Type     { public const char Code = 'u'; public const string Signature = "u"; }
+    public class Int64Type      { public const char Code = 'x'; public const string Signature = "x"; }
+    public class UInt64Type     { public const char Code = 't'; public const string Signature = "t"; }
+    public class DoubleType     { public const char Code = 'd'; public const string Signature = "d"; }
+    public class StringType     { public const char Code = 's'; public const string Signature = "s"; }
+    public class ObjectPathType { public const char Code = 'o'; public const string Signature = "o"; }
+    public class SignatureType  { public const char Code = 'g'; public const string Signature = "g"; }
+    public class ArrayType      { public const char Code = 'a'; public const string Signature = "a"; }
+    public class StructType     { public const char Code = 'r'; public const string Signature = "r"; }
+    public class VariantType    { public const char Code = 'v'; public const string Signature = "v"; }
+    public class DictEntryType  { public const char Code = 'e'; public const string Signature = "e"; }
+    public class UnixFdType     { public const char Code = 'h'; public const string Signature = "h"; }
+
+//     public static readonly ByteType       ByteT       = new ByteType();
+//     public static readonly BooleanType    BooleanT    = new BooleanType();
+//     public static readonly Int16Type      Int16T      = new Int16Type();
+//     public static readonly UInt16Type     UInt16T     = new UInt16Type();
+//     public static readonly Int32Type      Int32T      = new Int32Type();
+//     public static readonly UInt32Type     UInt32T     = new UInt32Type();
+//     public static readonly Int64Type      Int64T      = new Int64Type();
+//     public static readonly UInt64Type     UInt64T     = new UInt64Type();
+//     public static readonly DoubleType     DoubleT     = new DoubleType();
+//     public static readonly StringType     StringT     = new StringType();
+//     public static readonly ObjectPathType ObjectPathT = new ObjectPathType();
+//     public static readonly SignatureType  SignatureT  = new SignatureType();
+//     public static readonly ArrayType      ArrayT      = new ArrayType();
+//     public static readonly StructType     StructT     = new StructType();
+//     public static readonly VariantType    VariantT    = new VariantType();
+//     public static readonly DictEntryType  DictEntryT  = new DictEntryType();
+//     public static readonly UnixFdType     UnixFdT     = new UnixFdType();
+//
+//     public static readonly ByteType       y = ByteT;
+//     public static readonly BooleanType    b = BooleanT;
+//     public static readonly Int16Type      n = Int16T;
+//     public static readonly UInt16Type     q = UInt16T;
+//     public static readonly Int32Type      i = Int32T;
+//     public static readonly UInt32Type     u = UInt32T;
+//     public static readonly Int64Type      x = Int64T;
+//     public static readonly UInt64Type     t = UInt64T;
+//     public static readonly DoubleType     d = DoubleT;
+//     public static readonly StringType     s = StringT;
+//     public static readonly ObjectPathType o = ObjectPathT;
+//     public static readonly SignatureType  g = SignatureT;
+//     public static readonly ArrayType      a = ArrayT;
+//     public static readonly StructType     r = StructT;
+//     public static readonly VariantType    v = VariantT;
+//     public static readonly DictEntryType  e = DictEntryT;
+//     public static readonly UnixFdType     h = UnixFdT;
+}
+
+public abstract class BasicMessageArgument
+{
+    public void AppendTo(eldbus.Message msg)
+    {
+        if (!InternalAppendTo(msg))
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not append basic type to eldbus.Message");
+        }
+    }
+
+    public void AppendTo(eldbus.MessageIterator iter)
+    {
+        if (!InternalAppendTo(iter))
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not append basic type to eldbus.MessageIterator");
+        }
+    }
+
+    public abstract char TypeCode {get;}
+    public abstract string Signature {get;}
+    protected abstract bool InternalAppendTo(eldbus.Message msg);
+    protected abstract bool InternalAppendTo(eldbus.MessageIterator iter);
+
+    public static implicit operator BasicMessageArgument(byte arg)
+    {
+        return new ByteMessageArgument(arg);
+    }
+
+    public static implicit operator BasicMessageArgument(bool arg)
+    {
+        return new BoolMessageArgument(arg);
+    }
+
+    public static implicit operator BasicMessageArgument(Int16 arg)
+    {
+        return new Int16MessageArgument(arg);
+    }
+
+    public static implicit operator BasicMessageArgument(UInt16 arg)
+    {
+        return new UInt16MessageArgument(arg);
+    }
+
+    public static implicit operator BasicMessageArgument(Int32 arg)
+    {
+        return new Int32MessageArgument(arg);
+    }
+
+    public static implicit operator BasicMessageArgument(UInt32 arg)
+    {
+        return new UInt32MessageArgument(arg);
+    }
+
+    public static implicit operator BasicMessageArgument(Int64 arg)
+    {
+        return new Int64MessageArgument(arg);
+    }
+
+    public static implicit operator BasicMessageArgument(UInt64 arg)
+    {
+        return new UInt64MessageArgument(arg);
+    }
+
+    public static implicit operator BasicMessageArgument(string arg)
+    {
+        return new StringMessageArgument(arg);
+    }
+
+    public static implicit operator BasicMessageArgument(SignatureString arg)
+    {
+        return new SignatureMessageArgument(arg);
+    }
+
+    public static implicit operator BasicMessageArgument(ObjectPath arg)
+    {
+        return new ObjectPathMessageArgument(arg);
+    }
+
+    public static implicit operator BasicMessageArgument(UnixFd arg)
+    {
+        return new UnixFdMessageArgument(arg);
+    }
+}
+
+public class ByteMessageArgument : BasicMessageArgument
+{
+    private byte value;
+
+    public ByteMessageArgument(byte arg)
+    {
+        value = arg;
+    }
+
+    public override char TypeCode { get { return Argument.ByteType.Code; } }
+    public override string Signature { get { return Argument.ByteType.Signature; } }
+
+    protected override bool InternalAppendTo(eldbus.Message msg)
+    {
+        return eldbus_message_arguments_append(msg.Handle, Signature, value);
+    }
+
+    protected override bool InternalAppendTo(eldbus.MessageIterator iter)
+    {
+        return eldbus_message_iter_basic_append(iter.Handle, TypeCode, value);
+    }
+}
+
+public class BoolMessageArgument : BasicMessageArgument
+{
+    private Int32 value;
+
+    public BoolMessageArgument(bool arg)
+    {
+        value = Convert.ToInt32(arg);
+    }
+
+    public override char TypeCode { get { return Argument.BooleanType.Code; } }
+    public override string Signature { get { return Argument.ByteType.Signature; } }
+
+    protected override bool InternalAppendTo(eldbus.Message msg)
+    {
+        return eldbus_message_arguments_append(msg.Handle, Signature, value);
+    }
+
+    protected override bool InternalAppendTo(eldbus.MessageIterator iter)
+    {
+        return eldbus_message_iter_basic_append(iter.Handle, TypeCode, value);
+    }
+}
+
+public class Int16MessageArgument : BasicMessageArgument
+{
+    private Int16 value;
+
+    public Int16MessageArgument(Int16 arg)
+    {
+        value = arg;
+    }
+
+    public override char TypeCode { get { return Argument.Int16Type.Code; } }
+    public override string Signature { get { return Argument.ByteType.Signature; } }
+
+    protected override bool InternalAppendTo(eldbus.Message msg)
+    {
+        return eldbus_message_arguments_append(msg.Handle, Signature, value);
+    }
+
+    protected override bool InternalAppendTo(eldbus.MessageIterator iter)
+    {
+        return eldbus_message_iter_basic_append(iter.Handle, TypeCode, value);
+    }
+}
+
+public class UInt16MessageArgument : BasicMessageArgument
+{
+    private UInt16 value;
+
+    public UInt16MessageArgument(UInt16 arg)
+    {
+        value = arg;
+    }
+
+    public override char TypeCode { get { return Argument.UInt16Type.Code; } }
+    public override string Signature { get { return Argument.ByteType.Signature; } }
+
+    protected override bool InternalAppendTo(eldbus.Message msg)
+    {
+        return eldbus_message_arguments_append(msg.Handle, Signature, value);
+    }
+
+    protected override bool InternalAppendTo(eldbus.MessageIterator iter)
+    {
+        return eldbus_message_iter_basic_append(iter.Handle, TypeCode, value);
+    }
+}
+
+public class Int32MessageArgument : BasicMessageArgument
+{
+    private Int32 value;
+
+    public Int32MessageArgument(Int32 arg)
+    {
+        value = arg;
+    }
+
+    public override char TypeCode { get { return Argument.Int32Type.Code; } }
+    public override string Signature { get { return Argument.ByteType.Signature; } }
+
+    protected override bool InternalAppendTo(eldbus.Message msg)
+    {
+        return eldbus_message_arguments_append(msg.Handle, Signature, value);
+    }
+
+    protected override bool InternalAppendTo(eldbus.MessageIterator iter)
+    {
+        return eldbus_message_iter_basic_append(iter.Handle, TypeCode, value);
+    }
+}
+
+public class UInt32MessageArgument : BasicMessageArgument
+{
+    private UInt32 value;
+
+    public UInt32MessageArgument(UInt32 arg)
+    {
+        value = arg;
+    }
+
+    public override char TypeCode { get { return Argument.UInt32Type.Code; } }
+    public override string Signature { get { return Argument.ByteType.Signature; } }
+
+    protected override bool InternalAppendTo(eldbus.Message msg)
+    {
+        return eldbus_message_arguments_append(msg.Handle, Signature, value);
+    }
+
+    protected override bool InternalAppendTo(eldbus.MessageIterator iter)
+    {
+        return eldbus_message_iter_basic_append(iter.Handle, TypeCode, value);
+    }
+}
+
+public class Int64MessageArgument : BasicMessageArgument
+{
+    private Int64 value;
+
+    public Int64MessageArgument(Int64 arg)
+    {
+        value = arg;
+    }
+
+    public override char TypeCode { get { return Argument.Int64Type.Code; } }
+    public override string Signature { get { return Argument.ByteType.Signature; } }
+
+    protected override bool InternalAppendTo(eldbus.Message msg)
+    {
+        return eldbus_message_arguments_append(msg.Handle, Signature, value);
+    }
+
+    protected override bool InternalAppendTo(eldbus.MessageIterator iter)
+    {
+        return eldbus_message_iter_basic_append(iter.Handle, TypeCode, value);
+    }
+}
+
+public class UInt64MessageArgument : BasicMessageArgument
+{
+    private UInt64 value;
+
+    public UInt64MessageArgument(UInt64 arg)
+    {
+        value = arg;
+    }
+
+    public override char TypeCode { get { return Argument.UInt64Type.Code; } }
+    public override string Signature { get { return Argument.ByteType.Signature; } }
+
+    protected override bool InternalAppendTo(eldbus.Message msg)
+    {
+        return eldbus_message_arguments_append(msg.Handle, Signature, value);
+    }
+
+    protected override bool InternalAppendTo(eldbus.MessageIterator iter)
+    {
+        return eldbus_message_iter_basic_append(iter.Handle, TypeCode, value);
+    }
+}
+
+public class DoubleMessageArgument : BasicMessageArgument
+{
+    private double value;
+
+    public DoubleMessageArgument(double arg)
+    {
+        value = arg;
+    }
+
+    public override char TypeCode { get { return Argument.DoubleType.Code; } }
+    public override string Signature { get { return Argument.ByteType.Signature; } }
+
+    protected override bool InternalAppendTo(eldbus.Message msg)
+    {
+        return eldbus_message_arguments_append(msg.Handle, Signature, value);
+    }
+
+    protected override bool InternalAppendTo(eldbus.MessageIterator iter)
+    {
+        return eldbus_message_iter_basic_append(iter.Handle, TypeCode, value);
+    }
+}
+
+public abstract class StringLikeMessageArgument : BasicMessageArgument
+{
+    private string value;
+
+    public StringLikeMessageArgument(string arg)
+    {
+        value = arg;
+    }
+
+    protected override bool InternalAppendTo(eldbus.Message msg)
+    {
+        return eldbus_message_arguments_append(msg.Handle, Signature, value);
+    }
+
+    protected override bool InternalAppendTo(eldbus.MessageIterator iter)
+    {
+        return eldbus_message_iter_basic_append(iter.Handle, TypeCode, value);
+    }
+}
+
+public class StringMessageArgument : StringLikeMessageArgument
+{
+    public StringMessageArgument(string arg)
+        : base(arg)
+    {}
+
+    public override char TypeCode { get { return Argument.StringType.Code; } }
+    public override string Signature { get { return Argument.ByteType.Signature; } }
+}
+
+public class ObjectPathMessageArgument : StringLikeMessageArgument
+{
+    public ObjectPathMessageArgument(ObjectPath arg)
+        : base(arg.value)
+    {}
+
+    public override char TypeCode { get { return Argument.ObjectPathType.Code; } }
+    public override string Signature { get { return Argument.ByteType.Signature; } }
+}
+
+public class SignatureMessageArgument : StringLikeMessageArgument
+{
+    public SignatureMessageArgument(SignatureString arg)
+        : base(arg.value)
+    {}
+
+    public override char TypeCode { get { return Argument.SignatureType.Code; } }
+    public override string Signature { get { return Argument.ByteType.Signature; } }
+}
+
+public class UnixFdMessageArgument : BasicMessageArgument
+{
+    private Int32 value;
+
+    public UnixFdMessageArgument(UnixFd arg)
+    {
+        value = arg.value;
+    }
+
+    public override char TypeCode { get { return Argument.UnixFdType.Code; } }
+    public override string Signature { get { return Argument.ByteType.Signature; } }
+
+    protected override bool InternalAppendTo(eldbus.Message msg)
+    {
+        return eldbus_message_arguments_append(msg.Handle, Signature, value);
+    }
+
+    protected override bool InternalAppendTo(eldbus.MessageIterator iter)
+    {
+        return eldbus_message_iter_basic_append(iter.Handle, TypeCode, value);
+    }
+}
+
+public delegate void MessageDelegate(eldbus.Message msg, eldbus.Pending pending);
+
+public static class Common
+{
+    public static void RaiseNullHandle()
+    {
+        if (NullHandleError == 0)
+            NullHandleError = eina.Error.Register("Eldbus: null handle");
+        eina.Error.Raise(NullHandleError);
+    }
+
+    public delegate void Eldbus_Message_Cb(IntPtr data, IntPtr msg, IntPtr pending);
+
+    public static IntPtr GetMessageCbWrapperPtr()
+    {
+        return Marshal.GetFunctionPointerForDelegate(GetMessageCbWrapper());
+    }
+
+    public static Eldbus_Message_Cb GetMessageCbWrapper()
+    {
+        if (message_cb_wrapper == null)
+            message_cb_wrapper = new Eldbus_Message_Cb(MessageCbWrapper);
+        return message_cb_wrapper;
+    }
+
+    public static void MessageCbWrapper(IntPtr data, IntPtr msg_hdl, IntPtr pending_hdl)
+    {
+        MessageDelegate dlgt = Marshal.GetDelegateForFunctionPointer(data, typeof(MessageDelegate)) as MessageDelegate;
+        if (dlgt == null)
+        {
+            eina.Log.Error("Eldbus: invalid delegate pointer from Eldbus_Message_Cb");
+            return;
+        }
+
+        eldbus.Message msg;
+        eldbus.Pending pending;
+
+        try
+        {
+            msg = new eldbus.Message(msg_hdl, false);
+            pending = new eldbus.Pending(pending_hdl, false);
+        }
+        catch(Exception e)
+        {
+            eina.Log.Error("Eldbus: could not convert Eldbus_Message_Cb parameters. Exception: " + e.ToString());
+            return;
+        }
+
+        try
+        {
+            dlgt(msg, pending);
+        }
+        catch(Exception e)
+        {
+            eina.Log.Error("Eldbus: Eldbus_Message_Cb delegate error. Exception: " + e.ToString());
+        }
+    }
+
+    private static Eldbus_Message_Cb message_cb_wrapper = null;
+    private static eina.Error NullHandleError = 0;
+}
+
+}
+
+
diff --git a/src/bindings/mono/eldbus_mono/eldbus_config.cs b/src/bindings/mono/eldbus_mono/eldbus_config.cs
new file mode 100644 (file)
index 0000000..f605481
--- /dev/null
@@ -0,0 +1,24 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace eldbus {
+
+public static class Config
+{
+    [DllImport(efl.Libs.Eldbus)] private static extern int eldbus_init();
+    [DllImport(efl.Libs.Eldbus)] private static extern int eldbus_shutdown();
+
+    public static void Init()
+    {
+        if (eldbus_init() == 0)
+            throw new efl.EflException("Failed to initialize Eldbus");
+    }
+
+    public static void Shutdown()
+    {
+        eldbus_shutdown();
+    }
+
+}
+
+}
diff --git a/src/bindings/mono/eldbus_mono/eldbus_connection.cs b/src/bindings/mono/eldbus_mono/eldbus_connection.cs
new file mode 100644 (file)
index 0000000..87d09cb
--- /dev/null
@@ -0,0 +1,373 @@
+using System;
+using System.Runtime.InteropServices;
+
+using static eldbus.EldbusConnectionNativeFunctions;
+
+namespace eldbus {
+
+
+public static class EldbusConnectionNativeFunctions
+{
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_connection_get(eldbus.Connection.Type type);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_private_connection_get(eldbus.Connection.Type type);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_address_connection_get(string address);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_private_address_connection_get(string address);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_connection_ref(IntPtr conn);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_connection_unref(IntPtr conn);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_connection_free_cb_add(IntPtr conn, IntPtr cb, IntPtr data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_connection_free_cb_del(IntPtr conn, IntPtr cb, IntPtr data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_connection_data_set(IntPtr conn, IntPtr key, IntPtr data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_connection_data_get(IntPtr conn, IntPtr key);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_connection_data_del(IntPtr conn, IntPtr key);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_connection_event_callback_add(IntPtr conn, int type, IntPtr cb, IntPtr cb_data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_connection_event_callback_del(IntPtr conn, int type, IntPtr cb, IntPtr cb_data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_connection_send(IntPtr conn, IntPtr msg, IntPtr cb, IntPtr cb_data, double timeout);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_connection_unique_name_get(IntPtr conn);
+
+    // FreeDesktop.Org Methods
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_name_request(IntPtr conn, string bus, uint flags, IntPtr cb, IntPtr cb_data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_name_release(IntPtr conn, string bus, IntPtr cb, IntPtr cb_data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_name_owner_get(IntPtr conn, string bus, IntPtr cb, IntPtr cb_data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_name_owner_has(IntPtr conn, string bus, IntPtr cb, IntPtr cb_data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_names_list(IntPtr conn, IntPtr cb, IntPtr cb_data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_names_activatable_list(IntPtr conn, IntPtr cb, IntPtr cb_data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_hello(IntPtr conn, IntPtr cb, IntPtr cb_data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_name_start(IntPtr conn, string bus, uint flags, IntPtr cb, IntPtr cb_data);
+
+//     typedef void (*Eldbus_Name_Owner_Changed_Cb)(void *data, const char *bus, const char *old_id, const char *new_id);
+//     [DllImport(efl.Libs.Eldbus)] public static extern void
+//         eldbus_name_owner_changed_callback_add(IntPtr conn, string bus, Eldbus_Name_Owner_Changed_Cb cb, IntPtr cb_data, [MarshalAs(UnmanagedType.U1)] bool allow_initial_call);
+//     [DllImport(efl.Libs.Eldbus)] public static extern void
+//         eldbus_name_owner_changed_callback_del(IntPtr conn, string bus, Eldbus_Name_Owner_Changed_Cb cb, IntPtr cb_data);
+}
+
+public class Connection : IDisposable
+{
+    public enum Type
+    {
+        Unknown = 0, // sentinel, not a real type
+        Session,
+        System,
+        Starter,
+        Address,
+        Last         // sentinel, not a real type
+    };
+
+    public IntPtr Handle {get;set;} = IntPtr.Zero;
+    public bool Own {get;set;} = true;
+
+    private void InitNew(IntPtr handle, bool own)
+    {
+        Handle = handle;
+        Own = own;
+        CheckHandle();
+    }
+
+    private void CheckHandle()
+    {
+        if (Handle == IntPtr.Zero)
+        {
+            eldbus.Common.RaiseNullHandle();
+        }
+    }
+
+    public Connection(IntPtr handle, bool own)
+    {
+        InitNew(handle, own);
+    }
+
+
+    public Connection(eldbus.Connection.Type type)
+    {
+        InitNew(eldbus_connection_get(type), true);
+    }
+
+    public Connection(string address)
+    {
+        InitNew(eldbus_address_connection_get(address), true);
+    }
+
+    public static eldbus.Connection GetPrivate(eldbus.Connection.Type type)
+    {
+        return new eldbus.Connection(eldbus_private_connection_get(type), true);
+    }
+
+    public static eldbus.Connection GetPrivate(string address)
+    {
+        return new eldbus.Connection(eldbus_private_address_connection_get(address), true);
+    }
+
+
+    ~Connection()
+    {
+        Dispose(false);
+    }
+
+    protected virtual void Dispose(bool disposing)
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        if (h == IntPtr.Zero)
+            return;
+
+        if (Own)
+            eldbus_connection_unref(h);
+    }
+
+    public void Dispose()
+    {
+        Dispose(true);
+        GC.SuppressFinalize(this);
+    }
+
+    public void Free()
+    {
+        Dispose();
+    }
+
+    public IntPtr Release()
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        return h;
+    }
+
+    public eldbus.Pending Send(eldbus.Message msg, eldbus.MessageDelegate dlgt = null, double timeout = -1)
+    {
+        CheckHandle();
+
+        if (msg == null)
+            throw new ArgumentNullException("msg");
+
+        IntPtr cb_wrapper = (dlgt == null ? IntPtr.Zero : eldbus.Common.GetMessageCbWrapperPtr());
+        IntPtr cb_data = (dlgt == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(dlgt));
+
+        var pending_hdl = eldbus_connection_send(Handle, msg.Handle, cb_wrapper, cb_data, timeout);
+
+        if(pending_hdl == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Pending' object from eldbus_connection_send");
+        }
+
+        msg.Ref();
+
+        return new eldbus.Pending(pending_hdl, false);
+    }
+
+    public string GetUniqueName()
+    {
+        CheckHandle();
+        var ptr = eldbus_connection_unique_name_get(Handle);
+        if (ptr == IntPtr.Zero)
+            return null;
+        return Marshal.PtrToStringAuto(ptr);
+    }
+
+    public eldbus.Pending NameRequest(string bus, uint flags, eldbus.MessageDelegate dlgt = null)
+    {
+        CheckHandle();
+
+        if (bus == null)
+            throw new ArgumentNullException("bus");
+
+        IntPtr cb_wrapper = (dlgt == null ? IntPtr.Zero : eldbus.Common.GetMessageCbWrapperPtr());
+        IntPtr cb_data = (dlgt == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(dlgt));
+
+        var pending_hdl = eldbus_name_request(Handle, bus, flags, cb_wrapper, cb_data);
+
+        if(pending_hdl == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Pending' object from eldbus_name_request");
+        }
+
+        return new eldbus.Pending(pending_hdl, false);
+    }
+
+    public eldbus.Pending NameRelease(string bus, eldbus.MessageDelegate dlgt = null)
+    {
+        CheckHandle();
+
+        if (bus == null)
+            throw new ArgumentNullException("bus");
+
+        IntPtr cb_wrapper = (dlgt == null ? IntPtr.Zero : eldbus.Common.GetMessageCbWrapperPtr());
+        IntPtr cb_data = (dlgt == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(dlgt));
+
+        var pending_hdl = eldbus_name_release(Handle, bus, cb_wrapper, cb_data);
+
+        if(pending_hdl == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Pending' object from eldbus_name_release");
+        }
+
+        return new eldbus.Pending(pending_hdl, false);
+    }
+
+    public eldbus.Pending GetNameOwner(string bus, eldbus.MessageDelegate dlgt = null)
+    {
+        CheckHandle();
+
+        if (bus == null)
+            throw new ArgumentNullException("bus");
+
+        IntPtr cb_wrapper = (dlgt == null ? IntPtr.Zero : eldbus.Common.GetMessageCbWrapperPtr());
+        IntPtr cb_data = (dlgt == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(dlgt));
+
+        var pending_hdl = eldbus_name_owner_get(Handle, bus, cb_wrapper, cb_data);
+
+        if(pending_hdl == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Pending' object from eldbus_name_owner_get");
+        }
+
+        return new eldbus.Pending(pending_hdl, false);
+    }
+
+    public eldbus.Pending HasNameOwner(string bus, eldbus.MessageDelegate dlgt = null)
+    {
+        CheckHandle();
+
+        if (bus == null)
+            throw new ArgumentNullException("bus");
+
+        IntPtr cb_wrapper = (dlgt == null ? IntPtr.Zero : eldbus.Common.GetMessageCbWrapperPtr());
+        IntPtr cb_data = (dlgt == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(dlgt));
+
+        var pending_hdl = eldbus_name_owner_has(Handle, bus, cb_wrapper, cb_data);
+
+        if(pending_hdl == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Pending' object from eldbus_name_owner_has");
+        }
+
+        return new eldbus.Pending(pending_hdl, false);
+    }
+
+    public eldbus.Pending NameList(eldbus.MessageDelegate dlgt = null)
+    {
+        CheckHandle();
+
+        IntPtr cb_wrapper = (dlgt == null ? IntPtr.Zero : eldbus.Common.GetMessageCbWrapperPtr());
+        IntPtr cb_data = (dlgt == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(dlgt));
+
+        var pending_hdl = eldbus_names_list(Handle, cb_wrapper, cb_data);
+
+        if(pending_hdl == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Pending' object from eldbus_names_list");
+        }
+
+        return new eldbus.Pending(pending_hdl, false);
+    }
+
+    public eldbus.Pending ActivableList(eldbus.MessageDelegate dlgt = null)
+    {
+        CheckHandle();
+
+        IntPtr cb_wrapper = (dlgt == null ? IntPtr.Zero : eldbus.Common.GetMessageCbWrapperPtr());
+        IntPtr cb_data = (dlgt == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(dlgt));
+
+        var pending_hdl = eldbus_names_activatable_list(Handle, cb_wrapper, cb_data);
+
+        if(pending_hdl == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Pending' object from eldbus_names_activatable_list");
+        }
+
+        return new eldbus.Pending(pending_hdl, false);
+    }
+
+    public eldbus.Pending Hello(eldbus.MessageDelegate dlgt = null)
+    {
+        CheckHandle();
+
+        IntPtr cb_wrapper = (dlgt == null ? IntPtr.Zero : eldbus.Common.GetMessageCbWrapperPtr());
+        IntPtr cb_data = (dlgt == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(dlgt));
+
+        var pending_hdl = eldbus_hello(Handle, cb_wrapper, cb_data);
+
+        if(pending_hdl == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Pending' object from eldbus_hello");
+        }
+
+        return new eldbus.Pending(pending_hdl, false);
+    }
+
+    public eldbus.Pending NameStart(string bus, uint flags, eldbus.MessageDelegate dlgt = null)
+    {
+        CheckHandle();
+
+        if (bus == null)
+            throw new ArgumentNullException("bus");
+
+        IntPtr cb_wrapper = (dlgt == null ? IntPtr.Zero : eldbus.Common.GetMessageCbWrapperPtr());
+        IntPtr cb_data = (dlgt == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(dlgt));
+
+        var pending_hdl = eldbus_name_start(Handle, bus, flags, cb_wrapper, cb_data);
+
+        if(pending_hdl == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Pending' object from eldbus_name_start");
+        }
+
+        return new eldbus.Pending(pending_hdl, false);
+    }
+
+}
+
+}
diff --git a/src/bindings/mono/eldbus_mono/eldbus_message.cs b/src/bindings/mono/eldbus_mono/eldbus_message.cs
new file mode 100644 (file)
index 0000000..2ebc90c
--- /dev/null
@@ -0,0 +1,924 @@
+using System;
+using System.Runtime.InteropServices;
+
+using static eldbus.EldbusMessageNativeFunctions;
+
+namespace eldbus {
+
+public static class EldbusMessageNativeFunctions
+{
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_message_ref(IntPtr msg);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_message_unref(IntPtr msg);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_message_path_get(IntPtr msg);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_message_interface_get(IntPtr msg);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_message_member_get(IntPtr msg);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_message_destination_get(IntPtr msg);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_message_sender_get(IntPtr msg);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_message_signature_get(IntPtr msg);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_message_method_call_new(string dest, string path, string iface, string method);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_message_signal_new(string path, string _interface, string name);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_message_error_new(IntPtr msg, string error_name, string error_msg);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_message_method_return_new(IntPtr msg);
+
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_error_get(IntPtr msg, out IntPtr name, out IntPtr text);
+
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_arguments_get(IntPtr msg, string signature, out byte value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_arguments_get(IntPtr msg, string signature, out Int16 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_arguments_get(IntPtr msg, string signature, out UInt16 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_arguments_get(IntPtr msg, string signature, out Int32 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_arguments_get(IntPtr msg, string signature, out UInt32 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_arguments_get(IntPtr msg, string signature, out Int64 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_arguments_get(IntPtr msg, string signature, out UInt64 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_arguments_get(IntPtr msg, string signature, out double value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_arguments_get(IntPtr msg, string signature, out IntPtr value);
+
+//     [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+//         eldbus_message_arguments_vget(IntPtr msg, string signature, va_list ap);
+
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_arguments_append(IntPtr msg, string signature, byte value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_arguments_append(IntPtr msg, string signature, Int16 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_arguments_append(IntPtr msg, string signature, UInt16 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_arguments_append(IntPtr msg, string signature, Int32 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_arguments_append(IntPtr msg, string signature, UInt32 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_arguments_append(IntPtr msg, string signature, Int64 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_arguments_append(IntPtr msg, string signature, UInt64 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_arguments_append(IntPtr msg, string signature, double value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_arguments_append(IntPtr msg, string signature, string value);
+
+//     [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+//         eldbus_message_arguments_vappend(IntPtr msg, string signature, va_list ap);
+
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_message_iter_container_new(IntPtr iter, int type, string contained_signature);
+
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_basic_append(IntPtr iter, int type, byte value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_basic_append(IntPtr iter, int type, Int16 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_basic_append(IntPtr iter, int type, UInt16 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_basic_append(IntPtr iter, int type, Int32 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_basic_append(IntPtr iter, int type, UInt32 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_basic_append(IntPtr iter, int type, Int64 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_basic_append(IntPtr iter, int type, UInt64 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_basic_append(IntPtr iter, int type, double value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_basic_append(IntPtr iter, int type, string value);
+
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_arguments_append(IntPtr iter, string signature, out IntPtr value);
+
+//     [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+//         eldbus_message_iter_arguments_vappend(IntPtr iter, string signature, va_list ap);
+
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_fixed_array_append(IntPtr iter, int type, IntPtr array, uint size);
+
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_container_close(IntPtr iter, IntPtr sub);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_message_iter_get(IntPtr msg);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_message_iter_basic_get(IntPtr iter, out byte value);
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_message_iter_basic_get(IntPtr iter, out Int16 value);
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_message_iter_basic_get(IntPtr iter, out UInt16 value);
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_message_iter_basic_get(IntPtr iter, out Int32 value);
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_message_iter_basic_get(IntPtr iter, out UInt32 value);
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_message_iter_basic_get(IntPtr iter, out Int64 value);
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_message_iter_basic_get(IntPtr iter, out UInt64 value);
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_message_iter_basic_get(IntPtr iter, out double value);
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_message_iter_basic_get(IntPtr iter, out IntPtr value);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern string
+        eldbus_message_iter_signature_get(IntPtr iter);
+
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_next(IntPtr iter);
+
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_get_and_next(IntPtr iter, char signature, out byte value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_get_and_next(IntPtr iter, char signature, out Int16 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_get_and_next(IntPtr iter, char signature, out UInt16 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_get_and_next(IntPtr iter, char signature, out Int32 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_get_and_next(IntPtr iter, char signature, out UInt32 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_get_and_next(IntPtr iter, char signature, out Int64 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_get_and_next(IntPtr iter, char signature, out UInt64 value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_get_and_next(IntPtr iter, char signature, out double value);
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_get_and_next(IntPtr iter, char signature, out IntPtr value);
+
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_fixed_array_get(IntPtr iter, int signature, out IntPtr value, out int n_elements);
+
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_message_iter_arguments_get(IntPtr iter, string signature, out IntPtr value);
+
+//     [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+//         eldbus_message_iter_arguments_vget(IntPtr iter, string signature, va_list ap);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_message_iter_del(IntPtr iter);
+}
+
+
+public class Message : IDisposable
+{
+    public IntPtr Handle {get;set;} = IntPtr.Zero;
+    public bool Own {get;set;} = true;
+
+    private void InitNew(IntPtr handle, bool own)
+    {
+        Handle = handle;
+        Own = own;
+        CheckHandle();
+    }
+
+    private void CheckHandle()
+    {
+        if (Handle == IntPtr.Zero)
+        {
+            eldbus.Common.RaiseNullHandle();
+        }
+    }
+
+    public Message(IntPtr handle, bool own)
+    {
+        InitNew(handle, own);
+    }
+
+    ~Message()
+    {
+        Dispose(false);
+    }
+
+    protected virtual void Dispose(bool disposing)
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        if (h == IntPtr.Zero)
+            return;
+
+        if (Own)
+            eldbus_message_unref(h);
+    }
+
+    public void Dispose()
+    {
+        Dispose(true);
+        GC.SuppressFinalize(this);
+    }
+
+    public void Free()
+    {
+        Dispose();
+    }
+
+    public IntPtr Release()
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        return h;
+    }
+
+    public static eldbus.Message NewMethodCall(string dest, string path, string iface, string method)
+    {
+        var ptr = eldbus_message_method_call_new(dest, path, iface, method);
+        if (ptr == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Message' object from eldbus_message_method_call_new");
+        }
+        return new eldbus.Message(ptr, true);
+    }
+
+    public static eldbus.Message NewSignal(string path, string _interface, string name)
+    {
+        var ptr = eldbus_message_signal_new(path, _interface, name);
+        if (ptr == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Message' object from eldbus_message_signal_new");
+        }
+        return new eldbus.Message(ptr, true);
+    }
+
+    public void Ref()
+    {
+        CheckHandle();
+        eldbus_message_ref(Handle);
+    }
+
+    public void Unref()
+    {
+        CheckHandle();
+        eldbus_message_unref(Handle);
+    }
+
+    public string GetPath()
+    {
+        CheckHandle();
+        var ptr = eldbus_message_path_get(Handle);
+        return Marshal.PtrToStringAuto(ptr);
+    }
+
+    public string GetInterface()
+    {
+        CheckHandle();
+        var ptr = eldbus_message_interface_get(Handle);
+        return Marshal.PtrToStringAuto(ptr);
+    }
+
+    public string GetMember()
+    {
+        CheckHandle();
+        var ptr = eldbus_message_member_get(Handle);
+        return Marshal.PtrToStringAuto(ptr);
+    }
+
+    public string GetDestination()
+    {
+        CheckHandle();
+        var ptr = eldbus_message_destination_get(Handle);
+        return Marshal.PtrToStringAuto(ptr);
+    }
+
+    public string GetSender()
+    {
+        CheckHandle();
+        var ptr = eldbus_message_sender_get(Handle);
+        return Marshal.PtrToStringAuto(ptr);
+    }
+
+    public string GetSignature()
+    {
+        CheckHandle();
+        var ptr = eldbus_message_signature_get(Handle);
+        return Marshal.PtrToStringAuto(ptr);
+    }
+
+    public eldbus.Message NewError(string error_name, string error_msg)
+    {
+        CheckHandle();
+        var ptr = eldbus_message_error_new(Handle, error_name, error_msg);
+        if (ptr == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Message' object from eldbus_message_error_new");
+        }
+        return new eldbus.Message(ptr, false);
+    }
+
+    public eldbus.Message NewMethodReturn()
+    {
+        CheckHandle();
+        var ptr = eldbus_message_method_return_new(Handle);
+        if (ptr == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Message' object from eldbus_message_method_return_new");
+        }
+        return new eldbus.Message(ptr, false);
+    }
+
+    public bool GetError(out string name, out string text)
+    {
+        CheckHandle();
+        IntPtr name_ptr;
+        IntPtr text_ptr;
+        bool r = eldbus_message_error_get(Handle, out name_ptr, out text_ptr);
+        name = Marshal.PtrToStringAuto(name_ptr);
+        text = Marshal.PtrToStringAuto(text_ptr);
+        return r;
+    }
+
+    public bool Get(out byte val)
+    {
+        CheckHandle();
+        return eldbus_message_arguments_get(Handle, Argument.ByteType.Signature, out val);
+    }
+
+    public bool Get(out bool val)
+    {
+        CheckHandle();
+        Int32 aux;
+        var r = eldbus_message_arguments_get(Handle, Argument.BooleanType.Signature, out aux);
+        val = (aux != 0);
+        return r;
+    }
+
+    public bool Get(out Int16 val)
+    {
+        CheckHandle();
+        return eldbus_message_arguments_get(Handle, Argument.Int16Type.Signature, out val);
+    }
+
+    public bool Get(out UInt16 val)
+    {
+        CheckHandle();
+        return eldbus_message_arguments_get(Handle, Argument.UInt16Type.Signature, out val);
+    }
+
+    public bool Get(out Int32 val)
+    {
+        CheckHandle();
+        return eldbus_message_arguments_get(Handle, Argument.Int32Type.Signature, out val);
+    }
+
+    public bool Get(out UInt32 val)
+    {
+        CheckHandle();
+        return eldbus_message_arguments_get(Handle, Argument.UInt32Type.Signature, out val);
+    }
+
+    public bool Get(out Int64 val)
+    {
+        CheckHandle();
+        return eldbus_message_arguments_get(Handle, Argument.Int64Type.Signature, out val);
+    }
+
+    public bool Get(out UInt64 val)
+    {
+        CheckHandle();
+        return eldbus_message_arguments_get(Handle, Argument.UInt64Type.Signature, out val);
+    }
+
+    public bool Get(out double val)
+    {
+        CheckHandle();
+        return eldbus_message_arguments_get(Handle, Argument.DoubleType.Signature, out val);
+    }
+
+    public bool Get(out string val)
+    {
+        CheckHandle();
+        IntPtr aux;
+        var r = eldbus_message_arguments_get(Handle, Argument.StringType.Signature, out aux);
+        val = Marshal.PtrToStringAuto(aux);
+        return r;
+    }
+
+    public bool Get(out eldbus.ObjectPath val)
+    {
+        CheckHandle();
+        IntPtr aux;
+        var r = eldbus_message_arguments_get(Handle, Argument.ObjectPathType.Signature, out aux);
+        val = Marshal.PtrToStringAuto(aux);
+        return r;
+    }
+
+    public bool Get(out eldbus.SignatureString val)
+    {
+        CheckHandle();
+        IntPtr aux;
+        var r = eldbus_message_arguments_get(Handle, Argument.SignatureType.Signature, out aux);
+        val = Marshal.PtrToStringAuto(aux);
+        return r;
+    }
+
+    public bool Get(out eldbus.UnixFd val)
+    {
+        CheckHandle();
+        Int32 aux;
+        var r = eldbus_message_arguments_get(Handle, Argument.UnixFdType.Signature, out aux);
+        val = aux;
+        return r;
+    }
+
+    public void Append(params BasicMessageArgument[] args)
+    {
+        CheckHandle();
+        foreach (BasicMessageArgument arg in args)
+        {
+            arg.AppendTo(this);
+        }
+    }
+
+    public eldbus.MessageIterator AppendOpenContainer(string signature)
+    {
+        var iter = GetMessageIterator();
+        return iter.AppendOpenContainer(signature);
+    }
+
+    public eldbus.MessageIterator GetMessageIterator()
+    {
+        CheckHandle();
+        var ptr = eldbus_message_iter_get(Handle);
+        if (ptr == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `MessageIterator' object from eldbus_message_iter_get");
+        }
+        return new eldbus.MessageIterator(ptr, IntPtr.Zero);
+    }
+}
+
+public class MessageIterator
+{
+    public IntPtr Handle {get;set;} = IntPtr.Zero;
+    public IntPtr Parent {get;set;} = IntPtr.Zero;
+
+    private void InitNew(IntPtr handle, IntPtr parent)
+    {
+        Handle = handle;
+        Parent = parent;
+        CheckHandle();
+    }
+
+    private void CheckHandle()
+    {
+        if (Handle == IntPtr.Zero)
+        {
+            eldbus.Common.RaiseNullHandle();
+        }
+    }
+
+    public MessageIterator(IntPtr handle, IntPtr parent)
+    {
+        InitNew(handle, parent);
+    }
+
+    public IntPtr Release()
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        Parent = IntPtr.Zero;
+        return h;
+    }
+
+    public void Append(params BasicMessageArgument[] args)
+    {
+        CheckHandle();
+
+        foreach (BasicMessageArgument arg in args)
+        {
+            arg.AppendTo(this);
+        }
+    }
+
+    public eldbus.MessageIterator AppendOpenContainer(string signature)
+    {
+        CheckHandle();
+
+        IntPtr new_iter = IntPtr.Zero;
+
+        if (signature[0] == 'v')
+        {
+            new_iter = eldbus_message_iter_container_new(Handle, 'v', signature.Substring(1));
+        }
+        else if (!eldbus_message_iter_arguments_append(Handle, signature, out new_iter))
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not append container type");
+        }
+
+        if (new_iter == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `MessageIterator' object from eldbus_message_iter_arguments_append");
+        }
+
+        return new eldbus.MessageIterator(new_iter, Handle);
+    }
+
+    public eldbus.MessageIterator AppendOpenContainer(char type, string contained_signature)
+    {
+        CheckHandle();
+
+        IntPtr new_iter = eldbus_message_iter_container_new(Handle, type, contained_signature);
+
+        if (new_iter == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `MessageIterator' object from eldbus_message_iter_container_new");
+        }
+
+        return new eldbus.MessageIterator(new_iter, Handle);
+    }
+
+    public void CloseContainer()
+    {
+        CheckHandle();
+
+        if (Parent == IntPtr.Zero)
+        {
+            throw new SEHException("Eldbus: can not close MessageIterator open container without a parent");
+        }
+
+        if (!eldbus_message_iter_container_close(Parent, Handle))
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not close MessageIterator");
+        }
+
+        Handle = IntPtr.Zero;
+        Parent = IntPtr.Zero;
+    }
+
+    public string GetSignature()
+    {
+        return eldbus_message_iter_signature_get(Handle);
+    }
+
+    public bool GetAndNext(out byte val)
+    {
+        CheckHandle();
+        return eldbus_message_iter_get_and_next(Handle, Argument.ByteType.Code, out val);
+    }
+
+    public bool GetAndNext(out bool val)
+    {
+        CheckHandle();
+        Int32 aux;
+        bool r = eldbus_message_iter_get_and_next(Handle, Argument.BooleanType.Code, out aux);
+        val = (aux != 0);
+        return r;
+    }
+
+    public bool GetAndNext(out Int16 val)
+    {
+        CheckHandle();
+        return eldbus_message_iter_get_and_next(Handle, Argument.Int16Type.Code, out val);
+    }
+
+    public bool GetAndNext(out UInt16 val)
+    {
+        CheckHandle();
+        return eldbus_message_iter_get_and_next(Handle, Argument.UInt16Type.Code, out val);
+    }
+
+    public bool GetAndNext(out Int32 val)
+    {
+        CheckHandle();
+        return eldbus_message_iter_get_and_next(Handle, Argument.Int32Type.Code, out val);
+    }
+
+    public bool GetAndNext(out UInt32 val)
+    {
+        CheckHandle();
+        return eldbus_message_iter_get_and_next(Handle, Argument.UInt32Type.Code, out val);
+    }
+
+    public bool GetAndNext(out Int64 val)
+    {
+        CheckHandle();
+        return eldbus_message_iter_get_and_next(Handle, Argument.Int64Type.Code, out val);
+    }
+
+    public bool GetAndNext(out UInt64 val)
+    {
+        CheckHandle();
+        return eldbus_message_iter_get_and_next(Handle, Argument.UInt64Type.Code, out val);
+    }
+
+    public bool GetAndNext(out double val)
+    {
+        CheckHandle();
+        return eldbus_message_iter_get_and_next(Handle, Argument.DoubleType.Code, out val);
+    }
+
+    public bool GetAndNext(out string val)
+    {
+        CheckHandle();
+        IntPtr aux;
+        bool r = eldbus_message_iter_get_and_next(Handle, Argument.StringType.Code, out aux);
+        val = Marshal.PtrToStringAuto(aux);
+        return r;
+    }
+
+    public bool GetAndNext(out eldbus.ObjectPath val)
+    {
+        CheckHandle();
+        IntPtr aux;
+        bool r = eldbus_message_iter_get_and_next(Handle, Argument.ObjectPathType.Code, out aux);
+        val = Marshal.PtrToStringAuto(aux);
+        return r;
+    }
+
+    public bool GetAndNext(out eldbus.SignatureString val)
+    {
+        CheckHandle();
+        IntPtr aux;
+        bool r = eldbus_message_iter_get_and_next(Handle, Argument.SignatureType.Code, out aux);
+        val = Marshal.PtrToStringAuto(aux);
+        return r;
+    }
+
+    public bool GetAndNext(out eldbus.UnixFd val)
+    {
+        CheckHandle();
+        Int32 aux;
+        bool r = eldbus_message_iter_get_and_next(Handle, Argument.UnixFdType.Code, out aux);
+        val = aux;
+        return r;
+    }
+
+    public bool GetAndNext(out eldbus.MessageIterator iter, char typecode)
+    {
+        CheckHandle();
+        IntPtr hdl = IntPtr.Zero;
+        bool r = eldbus_message_iter_get_and_next(Handle, typecode, out hdl);
+        if (hdl == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get argument");
+        }
+        iter = new eldbus.MessageIterator(hdl, Handle);
+
+        return r;
+    }
+
+    public bool GetAndNext(out eldbus.MessageIterator iter, string signatue)
+    {
+        CheckHandle();
+        IntPtr hdl = IntPtr.Zero;
+        if (!eldbus_message_iter_arguments_get(Handle, signatue, out hdl) || hdl == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get argument");
+        }
+        iter = new eldbus.MessageIterator(hdl, Handle);
+
+        return Next();
+    }
+
+    public void Get(out byte val)
+    {
+        CheckHandle();
+        eldbus_message_iter_basic_get(Handle, out val);
+    }
+
+    public void Get(out bool val)
+    {
+        CheckHandle();
+        Int32 aux;
+        eldbus_message_iter_basic_get(Handle, out aux);
+        val = (aux != 0);
+    }
+
+    public void Get(out Int16 val)
+    {
+        CheckHandle();
+        eldbus_message_iter_basic_get(Handle, out val);
+    }
+
+    public void Get(out UInt16 val)
+    {
+        CheckHandle();
+        eldbus_message_iter_basic_get(Handle, out val);
+    }
+
+    public void Get(out Int32 val)
+    {
+        CheckHandle();
+        eldbus_message_iter_basic_get(Handle, out val);
+    }
+
+    public void Get(out UInt32 val)
+    {
+        CheckHandle();
+        eldbus_message_iter_basic_get(Handle, out val);
+    }
+
+    public void Get(out Int64 val)
+    {
+        CheckHandle();
+        eldbus_message_iter_basic_get(Handle, out val);
+    }
+
+    public void Get(out UInt64 val)
+    {
+        CheckHandle();
+        eldbus_message_iter_basic_get(Handle, out val);
+    }
+
+    public void Get(out double val)
+    {
+        CheckHandle();
+        eldbus_message_iter_basic_get(Handle, out val);
+    }
+
+    public void Get(out string val)
+    {
+        CheckHandle();
+        IntPtr aux;
+        eldbus_message_iter_basic_get(Handle, out aux);
+        val = Marshal.PtrToStringAuto(aux);
+    }
+
+    public void Get(out eldbus.ObjectPath val)
+    {
+        CheckHandle();
+        IntPtr aux;
+        eldbus_message_iter_basic_get(Handle, out aux);
+        val = Marshal.PtrToStringAuto(aux);
+    }
+
+    public void Get(out eldbus.SignatureString val)
+    {
+        CheckHandle();
+        IntPtr aux;
+        eldbus_message_iter_basic_get(Handle, out aux);
+        val = Marshal.PtrToStringAuto(aux);
+    }
+
+    public void Get(out eldbus.UnixFd val)
+    {
+        CheckHandle();
+        Int32 aux;
+        eldbus_message_iter_basic_get(Handle, out aux);
+        val = aux;
+    }
+
+    public void Get(out eldbus.MessageIterator iter, string signatue)
+    {
+        CheckHandle();
+        IntPtr hdl = IntPtr.Zero;
+        if (!eldbus_message_iter_arguments_get(Handle, signatue, out hdl) || hdl == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get argument");
+        }
+        iter = new eldbus.MessageIterator(hdl, Handle);
+    }
+
+    public bool Next()
+    {
+        CheckHandle();
+        return eldbus_message_iter_next(Handle);
+    }
+
+    public void Del()
+    {
+        CheckHandle();
+
+        eldbus_message_iter_del(Handle);
+
+        Handle = IntPtr.Zero;
+        Parent = IntPtr.Zero;
+    }
+
+    private void GetFixedArrayInternal(int type_code, out IntPtr value, out int n_elements)
+    {
+        CheckHandle();
+
+        if (!eldbus_message_iter_fixed_array_get(Handle, type_code, out value, out n_elements))
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get fixed array");
+        }
+    }
+
+    public void GetFixedArray(out byte[] array)
+    {
+        IntPtr value;
+        int n_elements;
+        GetFixedArrayInternal(Argument.ByteType.Code, out value, out n_elements);
+        array = new byte[n_elements];
+        Marshal.Copy(value, array, 0, n_elements);
+    }
+
+    public void GetFixedArray(out bool[] array)
+    {
+        IntPtr value;
+        int n_elements;
+        GetFixedArrayInternal(Argument.BooleanType.Code, out value, out n_elements);
+        var aux = new Int32[n_elements];
+        Marshal.Copy(value, aux, 0, n_elements);
+
+        // array = aux.Select(Convert.ToBoolean).ToArray();
+        array = Array.ConvertAll(aux, Convert.ToBoolean);
+    }
+
+    public void GetFixedArray(out Int16[] array)
+    {
+        IntPtr value;
+        int n_elements;
+        GetFixedArrayInternal(Argument.Int16Type.Code, out value, out n_elements);
+        array = new Int16[n_elements];
+        Marshal.Copy(value, array, 0, n_elements);
+    }
+
+//     public void GetFixedArray(out UInt16[] array)
+//     {
+//         IntPtr value;
+//         int n_elements;
+//         GetFixedArrayInternal(Argument.UInt16Type.Code, out value, out n_elements);
+//         array = new UInt16[n_elements];
+//         Marshal.Copy(value, array, 0, n_elements);
+//     }
+
+    public void GetFixedArray(out Int32[] array)
+    {
+        IntPtr value;
+        int n_elements;
+        GetFixedArrayInternal(Argument.Int32Type.Code, out value, out n_elements);
+        array = new Int32[n_elements];
+        Marshal.Copy(value, array, 0, n_elements);
+    }
+
+//     public void GetFixedArray(out UInt32[] array)
+//     {
+//         IntPtr value;
+//         int n_elements;
+//         GetFixedArrayInternal(Argument.UInt32Type.Code, out value, out n_elements);
+//         array = new UInt32[n_elements];
+//         Marshal.Copy(value, array, 0, n_elements);
+//     }
+
+    public void GetFixedArray(out Int64[] array)
+    {
+        IntPtr value;
+        int n_elements;
+        GetFixedArrayInternal(Argument.Int64Type.Code, out value, out n_elements);
+        array = new Int64[n_elements];
+        Marshal.Copy(value, array, 0, n_elements);
+    }
+
+//     public void GetFixedArray(out UInt64[] array)
+//     {
+//         IntPtr value;
+//         int n_elements;
+//         GetFixedArrayInternal(Argument.UInt64Type.Code, out value, out n_elements);
+//         array = new UInt64[n_elements];
+//         Marshal.Copy(value, array, 0, n_elements);
+//     }
+
+    public void GetFixedArray(out eldbus.UnixFd[] array)
+    {
+        IntPtr value;
+        int n_elements;
+        GetFixedArrayInternal(Argument.DoubleType.Code, out value, out n_elements);
+        var aux = new Int32[n_elements];
+        Marshal.Copy(value, aux, 0, n_elements);
+
+        array = Array.ConvertAll(aux, e => new UnixFd(e));
+    }
+}
+
+}
+
diff --git a/src/bindings/mono/eldbus_mono/eldbus_object.cs b/src/bindings/mono/eldbus_mono/eldbus_object.cs
new file mode 100644 (file)
index 0000000..1b0f4cb
--- /dev/null
@@ -0,0 +1,314 @@
+using System.Runtime.InteropServices;
+
+using static eldbus.EldbusObjectNativeFunctions;
+
+using IntPtr = System.IntPtr;
+
+namespace eldbus {
+
+
+public static class EldbusObjectNativeFunctions
+{
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_object_get(IntPtr conn, string bus, string path);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_object_ref(IntPtr obj);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_object_unref(IntPtr obj);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_object_free_cb_add(IntPtr obj, IntPtr cb, IntPtr data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_object_free_cb_del(IntPtr obj, IntPtr cb, IntPtr data);
+
+// typedef enum
+// {
+//    ELDBUS_OBJECT_EVENT_IFACE_ADDED = 0, /**< a parent path must have a ObjectManager interface */
+//    ELDBUS_OBJECT_EVENT_IFACE_REMOVED, /**< a parent path must have a ObjectManager interface */
+//    ELDBUS_OBJECT_EVENT_PROPERTY_CHANGED, /**< a property has changes */
+//    ELDBUS_OBJECT_EVENT_PROPERTY_REMOVED, /**< a property was removed */
+//    ELDBUS_OBJECT_EVENT_DEL,
+//    ELDBUS_OBJECT_EVENT_LAST    /**< sentinel, not a real event type */
+// } Eldbus_Object_Event_Type;
+//
+//     [DllImport(efl.Libs.Eldbus)] public static extern void
+//         eldbus_object_event_callback_add(IntPtr obj, Eldbus_Object_Event_Type type, IntPtr cb, IntPtr cb_data);
+//
+//     [DllImport(efl.Libs.Eldbus)] public static extern void
+//         eldbus_object_event_callback_del(IntPtr obj, Eldbus_Object_Event_Type type, IntPtr cb, IntPtr cb_data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_object_connection_get(IntPtr obj);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_object_bus_name_get(IntPtr obj);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_object_path_get(IntPtr obj);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_object_send(IntPtr obj, IntPtr msg, IntPtr cb, IntPtr cb_data, double timeout);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_object_signal_handler_add(IntPtr obj, string _interface, string member, IntPtr cb, IntPtr cb_data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_object_method_call_new(IntPtr obj, string _interface, string member);
+
+    // FreeDesktop.Org Methods
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_object_peer_ping(IntPtr obj, IntPtr cb, IntPtr data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_object_peer_machine_id_get(IntPtr obj, IntPtr cb, IntPtr data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_object_introspect(IntPtr obj, IntPtr cb, IntPtr data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_object_managed_objects_get(IntPtr obj, IntPtr cb, IntPtr data);
+
+//     [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+//         eldbus_object_manager_interfaces_added(IntPtr obj, Eldbus_Signal_Cb cb, IntPtr cb_data);
+//
+//     [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+//         eldbus_object_manager_interfaces_removed(IntPtr obj, Eldbus_Signal_Cb cb, IntPtr cb_data);
+}
+
+
+public class Object : System.IDisposable
+{
+
+    public IntPtr Handle {get;set;} = IntPtr.Zero;
+    public bool Own {get;set;} = true;
+
+    private void InitNew(IntPtr handle, bool own)
+    {
+        Handle = handle;
+        Own = own;
+        CheckHandle();
+    }
+
+    private void CheckHandle()
+    {
+        if (Handle == IntPtr.Zero)
+        {
+            eldbus.Common.RaiseNullHandle();
+        }
+    }
+
+    public Object(IntPtr handle, bool own)
+    {
+        InitNew(handle, own);
+    }
+
+    public Object(eldbus.Connection conn, string bus, string path)
+    {
+        if (conn == null)
+            throw new System.ArgumentNullException("conn");
+        if (bus == null)
+            throw new System.ArgumentNullException("bus");
+        if (path == null)
+            throw new System.ArgumentNullException("path");
+
+        var handle = eldbus_object_get(conn.Handle, bus, path);
+
+        if (handle == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Object' object from eldbus_object_get");
+        }
+
+        InitNew(handle, true);
+    }
+
+    ~Object()
+    {
+        Dispose(false);
+    }
+
+    protected virtual void Dispose(bool disposing)
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        if (h == IntPtr.Zero)
+            return;
+
+        if (Own)
+            eldbus_object_unref(h);
+    }
+
+    public void Dispose()
+    {
+        Dispose(true);
+        System.GC.SuppressFinalize(this);
+    }
+
+    public void Free()
+    {
+        Dispose();
+    }
+
+    public IntPtr Release()
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        return h;
+    }
+
+    public eldbus.Connection GetConnection()
+    {
+        CheckHandle();
+        var conn = eldbus_object_connection_get(Handle);
+
+        if (conn == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Connection' object from eldbus_object_connection_get");
+        }
+
+        return new eldbus.Connection(conn, false);
+    }
+
+    public string GetBusName()
+    {
+        CheckHandle();
+        var ptr = eldbus_object_bus_name_get(Handle);
+        return Marshal.PtrToStringAuto(ptr);
+    }
+
+    public string GetPath()
+    {
+        CheckHandle();
+        var ptr = eldbus_object_path_get(Handle);
+        return Marshal.PtrToStringAuto(ptr);
+    }
+
+    public void Ref()
+    {
+        CheckHandle();
+        eldbus_object_ref(Handle);
+    }
+
+    public void Unref()
+    {
+        CheckHandle();
+        eldbus_object_unref(Handle);
+    }
+
+    public eldbus.Pending Send(eldbus.Message msg, eldbus.MessageDelegate dlgt = null, double timeout = -1)
+    {
+        CheckHandle();
+
+        if (msg == null)
+            throw new System.ArgumentNullException("msg");
+
+        IntPtr cb_wrapper = dlgt == null ? IntPtr.Zero : eldbus.Common.GetMessageCbWrapperPtr();
+        IntPtr cb_data = dlgt == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(dlgt);
+
+        var pending_hdl = eldbus_object_send(Handle, msg.Handle, cb_wrapper, cb_data, timeout);
+
+        if (pending_hdl == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Pending' object from eldbus_object_send");
+        }
+
+        return new eldbus.Pending(pending_hdl, false);
+    }
+
+    public eldbus.Message NewMethodCall(string _interface, string member)
+    {
+        CheckHandle();
+
+        var hdl = eldbus_object_method_call_new(Handle, _interface, member);
+
+        if (hdl == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Message' object from eldbus_object_method_call_new");
+        }
+
+        return new eldbus.Message(hdl, false);
+    }
+
+    public eldbus.Pending PeerPing(eldbus.MessageDelegate dlgt = null)
+    {
+        CheckHandle();
+
+        IntPtr cb_wrapper = dlgt == null ? IntPtr.Zero : eldbus.Common.GetMessageCbWrapperPtr();
+        IntPtr cb_data = dlgt == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(dlgt);
+
+        var pending_hdl = eldbus_object_peer_ping(Handle, cb_wrapper, cb_data);
+
+        if (pending_hdl == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Pending' object from eldbus_object_peer_ping");
+        }
+
+        return new eldbus.Pending(pending_hdl, false);
+    }
+
+    public eldbus.Pending GetPeerMachineId(eldbus.MessageDelegate dlgt = null)
+    {
+        CheckHandle();
+
+        IntPtr cb_wrapper = dlgt == null ? IntPtr.Zero : eldbus.Common.GetMessageCbWrapperPtr();
+        IntPtr cb_data = dlgt == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(dlgt);
+
+        var pending_hdl = eldbus_object_peer_machine_id_get(Handle, cb_wrapper, cb_data);
+
+        if (pending_hdl == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Pending' object from eldbus_object_peer_machine_id_get");
+        }
+
+        return new eldbus.Pending(pending_hdl, false);
+    }
+
+    public eldbus.Pending Introspect(eldbus.MessageDelegate dlgt = null)
+    {
+        CheckHandle();
+
+        IntPtr cb_wrapper = dlgt == null ? IntPtr.Zero : eldbus.Common.GetMessageCbWrapperPtr();
+        IntPtr cb_data = dlgt == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(dlgt);
+
+        var pending_hdl = eldbus_object_introspect(Handle, cb_wrapper, cb_data);
+
+        if (pending_hdl == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Pending' object from eldbus_object_introspect");
+        }
+
+        return new eldbus.Pending(pending_hdl, false);
+    }
+
+    public eldbus.Pending GetManagedObjects(eldbus.MessageDelegate dlgt = null)
+    {
+        CheckHandle();
+
+        IntPtr cb_wrapper = dlgt == null ? IntPtr.Zero : eldbus.Common.GetMessageCbWrapperPtr();
+        IntPtr cb_data = dlgt == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(dlgt);
+
+        var pending_hdl = eldbus_object_managed_objects_get(Handle, cb_wrapper, cb_data);
+
+        if (pending_hdl == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Pending' object from eldbus_object_managed_objects_get");
+        }
+
+        return new eldbus.Pending(pending_hdl, false);
+    }
+
+}
+
+
+}
diff --git a/src/bindings/mono/eldbus_mono/eldbus_pending.cs b/src/bindings/mono/eldbus_mono/eldbus_pending.cs
new file mode 100644 (file)
index 0000000..9dff599
--- /dev/null
@@ -0,0 +1,109 @@
+using System;
+using System.Runtime.InteropServices;
+
+using static eldbus.EldbusPendingNativeFunctions;
+
+namespace eldbus {
+
+public static class EldbusPendingNativeFunctions
+{
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_pending_data_set(IntPtr pending, string key, IntPtr data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_pending_data_get(IntPtr pending, string key);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_pending_data_del(IntPtr pending, string key);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_pending_cancel(IntPtr pending);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_pending_destination_get(IntPtr pending);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_pending_path_get(IntPtr pending);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_pending_interface_get(IntPtr pending);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_pending_method_get(IntPtr pending);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_pending_free_cb_add(IntPtr pending, IntPtr cb, IntPtr data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_pending_free_cb_del(IntPtr pending, IntPtr cb, IntPtr data);
+}
+
+public class Pending
+{
+    public IntPtr Handle {get;set;} = IntPtr.Zero;
+    public bool Own {get;set;} = true;
+
+    private void InitNew(IntPtr handle, bool own)
+    {
+        Handle = handle;
+        Own = own;
+        CheckHandle();
+    }
+
+    private void CheckHandle()
+    {
+        if (Handle == IntPtr.Zero)
+        {
+            eldbus.Common.RaiseNullHandle();
+        }
+    }
+
+    public Pending(IntPtr handle, bool own)
+    {
+        InitNew(handle, own);
+    }
+
+    public IntPtr Release()
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        return h;
+    }
+
+    public void Cancel()
+    {
+        CheckHandle();
+        eldbus_pending_cancel(Handle);
+    }
+
+    public string GetDestination()
+    {
+        CheckHandle();
+        var ptr = eldbus_pending_destination_get(Handle);
+        return Marshal.PtrToStringAuto(ptr);
+    }
+
+    public string GetPath()
+    {
+        CheckHandle();
+        var ptr = eldbus_pending_path_get(Handle);
+        return Marshal.PtrToStringAuto(ptr);
+    }
+
+    public string GetInterface()
+    {
+        CheckHandle();
+        var ptr = eldbus_pending_interface_get(Handle);
+        return Marshal.PtrToStringAuto(ptr);
+    }
+
+    public string GetMethod()
+    {
+        CheckHandle();
+        var ptr = eldbus_pending_method_get(Handle);
+        return Marshal.PtrToStringAuto(ptr);
+    }
+}
+
+}
+
diff --git a/src/bindings/mono/eldbus_mono/eldbus_proxy.cs b/src/bindings/mono/eldbus_mono/eldbus_proxy.cs
new file mode 100644 (file)
index 0000000..1d07de7
--- /dev/null
@@ -0,0 +1,218 @@
+using System;
+using System.Runtime.InteropServices;
+
+using static eldbus.EldbusProxyNativeFunctions;
+
+namespace eldbus {
+
+public static class EldbusProxyNativeFunctions
+{
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_proxy_get(IntPtr obj, string _interface);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_proxy_ref(IntPtr proxy);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_proxy_unref(IntPtr proxy);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_proxy_object_get(IntPtr proxy);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_proxy_interface_get(IntPtr proxy);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_proxy_data_set(IntPtr proxy, string key, IntPtr data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_proxy_data_get(IntPtr proxy, string key);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_proxy_data_del(IntPtr proxy, string key);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_proxy_free_cb_add(IntPtr proxy, IntPtr cb, IntPtr data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_proxy_free_cb_del(IntPtr proxy, IntPtr cb, IntPtr data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_proxy_method_call_new(IntPtr proxy, string member);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_proxy_send(IntPtr proxy, IntPtr msg, IntPtr cb, IntPtr cb_data, double timeout);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_proxy_send_and_block(IntPtr proxy, IntPtr msg, double timeout);
+
+//     [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+//         eldbus_proxy_call(IntPtr proxy, string member, IntPtr cb, IntPtr cb_data, double timeout, string signature, ...);
+//
+//     [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+//         eldbus_proxy_vcall(IntPtr proxy, string member, IntPtr cb, IntPtr cb_data, double timeout, string signature, va_list ap);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_proxy_signal_handler_add(IntPtr proxy, string member, IntPtr cb, IntPtr cb_data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_proxy_event_callback_add(IntPtr proxy, int type, IntPtr cb, IntPtr cb_data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_proxy_event_callback_del(IntPtr proxy, int type, IntPtr cb, IntPtr cb_data);
+}
+
+public class Proxy : IDisposable
+{
+    public IntPtr Handle {get;set;} = IntPtr.Zero;
+    public bool Own {get;set;} = true;
+
+    private void InitNew(IntPtr handle, bool own)
+    {
+        Handle = handle;
+        Own = own;
+        CheckHandle();
+    }
+
+    private void CheckHandle()
+    {
+        if (Handle == IntPtr.Zero)
+        {
+            eldbus.Common.RaiseNullHandle();
+        }
+    }
+
+    public Proxy(IntPtr handle, bool own)
+    {
+        InitNew(handle, own);
+    }
+
+    public Proxy(eldbus.Object obj, string _interface)
+    {
+        InitNew(eldbus_proxy_get(obj.Handle, _interface), true);
+    }
+
+    ~Proxy()
+    {
+        Dispose(false);
+    }
+
+    protected virtual void Dispose(bool disposing)
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        if (h == IntPtr.Zero)
+            return;
+
+        if (Own)
+            eldbus_proxy_unref(h);
+    }
+
+    public void Dispose()
+    {
+        Dispose(true);
+        GC.SuppressFinalize(this);
+    }
+
+    public void Free()
+    {
+        Dispose();
+    }
+
+    public IntPtr Release()
+    {
+        IntPtr h = Handle;
+        Handle = IntPtr.Zero;
+        return h;
+    }
+
+    eldbus.Object GetObject()
+    {
+        CheckHandle();
+        var ptr = eldbus_proxy_object_get(Handle);
+        if (ptr == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Object' object from eldbus_proxy_object_get");
+        }
+        return new eldbus.Object(ptr, false);
+    }
+
+    string GetInterface()
+    {
+        CheckHandle();
+        var ptr = eldbus_proxy_interface_get(Handle);
+        return Marshal.PtrToStringAuto(ptr);
+    }
+
+    eldbus.Message NewMethodCall(string member)
+    {
+        CheckHandle();
+
+        if (member == null)
+            throw new ArgumentNullException("member");
+
+        var ptr = eldbus_proxy_method_call_new(Handle, member);
+        if (ptr == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Message' object from eldbus_proxy_method_call_new");
+        }
+        return new eldbus.Message(ptr, false);
+    }
+
+    eldbus.Pending Send(eldbus.Message msg, eldbus.MessageDelegate dlgt = null, double timeout = -1)
+    {
+        CheckHandle();
+
+        if (msg == null)
+            throw new ArgumentNullException("msg");
+
+        IntPtr cb_wrapper = dlgt == null ? IntPtr.Zero : eldbus.Common.GetMessageCbWrapperPtr();
+        IntPtr cb_data = dlgt == null ? IntPtr.Zero : Marshal.GetFunctionPointerForDelegate(dlgt);
+
+        var pending_hdl = eldbus_proxy_send(Handle, msg.Handle, cb_wrapper, cb_data, timeout);
+
+        if (pending_hdl == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Pending' object from eldbus_proxy_send");
+        }
+
+        return new eldbus.Pending(pending_hdl, false);
+    }
+
+    eldbus.Message SendAndBlock(eldbus.Message msg, double timeout = -1)
+    {
+        CheckHandle();
+        var ptr = eldbus_proxy_send_and_block(Handle, msg.Handle, timeout);
+        if (ptr == IntPtr.Zero)
+        {
+            eina.Error.RaiseIfOccurred();
+            throw new SEHException("Eldbus: could not get `Message' object from eldbus_proxy_send_and_block");
+        }
+        return new eldbus.Message(ptr, true);
+    }
+
+    eldbus.Pending Call(string member, eldbus.MessageDelegate dlgt, double timeout, params BasicMessageArgument[] args)
+    {
+        CheckHandle();
+
+        var msg = NewMethodCall(member);
+
+        foreach (BasicMessageArgument arg in args)
+        {
+            arg.AppendTo(msg);
+        }
+
+        return Send(msg, dlgt, timeout);
+    }
+
+    eldbus.Pending Call(string member, params BasicMessageArgument[] args)
+    {
+        return Call(member, null, -1.0, args);
+    }
+}
+
+}
+
diff --git a/src/bindings/mono/eldbus_mono/eldbus_service.cs b/src/bindings/mono/eldbus_mono/eldbus_service.cs
new file mode 100644 (file)
index 0000000..b3b5487
--- /dev/null
@@ -0,0 +1,66 @@
+using System;
+using System.Runtime.InteropServices;
+
+using static eldbus.EldbusServiceNativeFunctions;
+
+namespace eldbus {
+
+public static class EldbusServiceNativeFunctions
+{
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_service_interface_register(IntPtr conn, string path, IntPtr desc);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_service_interface_fallback_register(IntPtr conn, string path, IntPtr desc);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_service_interface_register2(IntPtr conn, string path, IntPtr desc);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_service_interface_fallback_register2(IntPtr conn, string path, IntPtr desc);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_service_interface_unregister(IntPtr iface);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_service_object_unregister(IntPtr iface);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_service_connection_get(IntPtr iface);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_service_object_path_get(IntPtr iface);
+
+//     [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+//         eldbus_service_signal_emit(IntPtr iface, uint signal_id, ...);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_service_signal_new(IntPtr iface, uint signal_id);
+
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_service_signal_send(IntPtr iface, IntPtr signal_msg);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern void
+        eldbus_service_object_data_set(IntPtr iface, string key, IntPtr data);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_service_object_data_get(IntPtr iface, string key);
+
+    [DllImport(efl.Libs.Eldbus)] public static extern IntPtr
+        eldbus_service_object_data_del(IntPtr iface, string key);
+
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_service_property_changed(IntPtr iface, string name);
+
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_service_property_invalidate_set(IntPtr iface, string name, [MarshalAs(UnmanagedType.U1)] bool is_invalidate);
+
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_service_object_manager_attach(IntPtr iface);
+
+    [DllImport(efl.Libs.Eldbus)] [return: MarshalAs(UnmanagedType.U1)] public static extern bool
+        eldbus_service_object_manager_detach(IntPtr iface);
+}
+
+}
+
diff --git a/src/bindings/mono/eo_mono/iwrapper.cs b/src/bindings/mono/eo_mono/iwrapper.cs
new file mode 100644 (file)
index 0000000..bd3ba50
--- /dev/null
@@ -0,0 +1,392 @@
+
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+using static eina.NativeCustomExportFunctions;
+
+namespace efl { namespace eo {
+
+public class Globals {
+    [DllImport(efl.Libs.Eo)] public static extern void efl_object_init();
+    [DllImport(efl.Libs.Eo)] public static extern void efl_object_shutdown();
+    [DllImport(efl.Libs.Eo)] public static extern IntPtr
+        _efl_add_internal_start([MarshalAs(UnmanagedType.LPStr)] String file, int line,
+                                IntPtr klass, IntPtr parent, byte is_ref, byte is_fallback);
+    [DllImport(efl.Libs.Eo)] public static extern IntPtr
+        _efl_add_end(IntPtr eo, byte is_ref, byte is_fallback);
+    [DllImport(efl.Libs.Eo)] public static extern IntPtr
+        efl_ref(IntPtr eo);
+    [DllImport(efl.Libs.Eo)] public static extern void
+        efl_unref(IntPtr eo);
+    [DllImport(efl.Libs.Eo)] public static extern IntPtr
+        efl_class_new(IntPtr class_description, IntPtr base0);
+    [DllImport(efl.Libs.Eo)] public static extern IntPtr
+        efl_class_new(IntPtr class_description, IntPtr base0, IntPtr base1);
+    [DllImport(efl.Libs.Eo)] public static extern IntPtr
+        efl_class_new(IntPtr class_description, IntPtr base0, IntPtr base1, IntPtr base2);
+    [DllImport(efl.Libs.Eo)] public static extern IntPtr
+        efl_class_new(IntPtr class_description, IntPtr base0, IntPtr base1, IntPtr base2, IntPtr base3);
+    [DllImport(efl.Libs.Eo)] public static extern IntPtr
+        efl_class_new(IntPtr class_description, IntPtr base0, IntPtr base1, IntPtr base2, IntPtr base3, IntPtr base4);
+    [DllImport(efl.Libs.Eo)] public static extern IntPtr
+        efl_class_new(IntPtr class_description, IntPtr base0, IntPtr base1, IntPtr base2, IntPtr base3, IntPtr base4, IntPtr base5);
+    [DllImport(efl.Libs.Eo)] public static extern IntPtr
+        efl_class_new(IntPtr class_description, IntPtr base0, IntPtr base1, IntPtr base2, IntPtr base3, IntPtr base4, IntPtr base5, IntPtr base6);
+    [DllImport(efl.Libs.Eo)] public static extern IntPtr
+        efl_class_new(IntPtr class_description, IntPtr base0, IntPtr base1, IntPtr base2, IntPtr base3, IntPtr base4, IntPtr base5, IntPtr base6, IntPtr base7);
+    [DllImport(efl.Libs.Eo)] public static extern byte efl_class_functions_set(IntPtr klass_id, IntPtr object_ops, IntPtr class_ops);
+    [DllImport(efl.Libs.Eo)] public static extern IntPtr efl_data_scope_get(IntPtr obj, IntPtr klass);
+    [DllImport(efl.Libs.Eo)] public static extern IntPtr efl_super(IntPtr obj, IntPtr klass);
+    [DllImport(efl.Libs.Eo)] public static extern IntPtr efl_class_get(IntPtr obj);
+#if WIN32
+    public static IntPtr RTLD_DEFAULT = new IntPtr(1);
+#else
+    public static IntPtr RTLD_DEFAULT = new IntPtr(0);
+#endif
+    [DllImport(efl.Libs.Evil)] public static extern IntPtr dlerror();
+    [DllImport(efl.Libs.Evil)] public static extern IntPtr dlsym
+       (IntPtr handle, [MarshalAs(UnmanagedType.LPStr)] String name);
+
+   [DllImport(efl.Libs.Eo)] public static extern bool efl_event_callback_priority_add(
+              System.IntPtr obj,
+              // FIXME commented to allow passing null stuff during test
+              /* ref efl.kw_event.Description desc, */
+              efl.kw_event.Description desc,
+              short priority,
+              efl.Event_Cb cb,
+              System.IntPtr data);
+   [DllImport(efl.Libs.Eo)] public static extern bool efl_event_callback_del(
+              System.IntPtr obj,
+              efl.kw_event.Description desc,
+              efl.Event_Cb cb,
+              System.IntPtr data);
+
+
+    public const int RTLD_NOW = 2;
+
+    public delegate byte class_initializer(IntPtr klass);
+    
+    public static IntPtr register_class(class_initializer initializer, IntPtr base_klass)
+    {
+        ClassDescription description;
+        description.version = 2; // EO_VERSION
+        description.name = "BoxInherit";
+        description.class_type = 0; // REGULAR
+        description.data_size = (UIntPtr)8;
+        description.class_initializer = IntPtr.Zero;
+        description.class_constructor = IntPtr.Zero;
+        description.class_destructor = IntPtr.Zero;
+
+        if(initializer != null)
+            description.class_initializer = Marshal.GetFunctionPointerForDelegate(initializer);
+
+        IntPtr description_ptr = eina.MemoryNative.Alloc(Marshal.SizeOf(description));
+        Marshal.StructureToPtr(description, description_ptr, false);
+      
+        eina.Log.Debug("Going to register!");
+        IntPtr klass = efl.eo.Globals.efl_class_new(description_ptr, base_klass, IntPtr.Zero);
+        if(klass == IntPtr.Zero)
+            eina.Log.Error("klass was not registered");
+        eina.Log.Debug("Registered?");
+        return klass;
+    }
+    public static IntPtr instantiate_start(IntPtr klass, efl.Object parent)
+    {
+        eina.Log.Debug("Instantiating");
+        System.IntPtr parent_ptr = System.IntPtr.Zero;
+        if(parent != null)
+            parent_ptr = parent.raw_handle;
+
+        System.IntPtr eo = efl.eo.Globals._efl_add_internal_start("file", 0, klass, parent_ptr, 0, 0);
+        return eo;
+    }
+
+    public static IntPtr instantiate_end(IntPtr eo) {
+        eina.Log.Debug("efl_add_internal_start returned");
+        eo = efl.eo.Globals._efl_add_end(eo, 0, 0);
+        eina.Log.Debug("efl_add_end returned");
+        return eo;
+    }
+    public static void data_set(efl.eo.IWrapper obj)
+    {
+      IntPtr pd = efl.eo.Globals.efl_data_scope_get(obj.raw_handle, obj.raw_klass);
+      {
+          GCHandle gch = GCHandle.Alloc(obj);
+          EolianPD epd;
+          epd.pointer = GCHandle.ToIntPtr(gch);
+          Marshal.StructureToPtr(epd, pd, false);
+      }
+    }
+    public static efl.eo.IWrapper data_get(IntPtr pd)
+    {
+        EolianPD epd = (EolianPD)Marshal.PtrToStructure(pd, typeof(EolianPD));
+        if(epd.pointer != IntPtr.Zero)
+        {
+            GCHandle gch = GCHandle.FromIntPtr(epd.pointer);
+            return (efl.eo.IWrapper)gch.Target;
+        }
+        else
+            return null;
+    }
+
+    public static IntPtr cached_string_to_intptr(Dictionary<String, IntPtr> dict, String str)
+    {
+        IntPtr ptr = IntPtr.Zero;
+        if (!dict.TryGetValue(str, out ptr))
+        {
+            ptr = eina.StringConversion.ManagedStringToNativeUtf8Alloc(str);
+            dict[str] = ptr;
+        }
+
+        return ptr;
+    }
+
+    public static IntPtr cached_stringshare_to_intptr(Dictionary<String, IntPtr> dict, String str)
+    {
+        IntPtr ptr = IntPtr.Zero;
+        if (!dict.TryGetValue(str, out ptr))
+        {
+            ptr = eina.Stringshare.eina_stringshare_add(str);
+            dict[str] = ptr;
+        }
+
+        return ptr;
+    }
+
+    public static void free_dict_values(Dictionary<String, IntPtr> dict)
+    {
+        foreach(IntPtr ptr in dict.Values)
+        {
+            eina.MemoryNative.Free(ptr);
+        }
+    }
+
+    public static void free_stringshare_values(Dictionary<String, IntPtr> dict)
+    {
+        foreach(IntPtr ptr in dict.Values)
+        {
+            eina.Stringshare.eina_stringshare_del(ptr);
+        }
+    }
+
+    public static void free_gchandle(IntPtr ptr)
+    {
+        GCHandle handle = GCHandle.FromIntPtr(ptr);
+        handle.Free();
+    }
+}
+
+public static class Config
+{
+    public static void Init()
+    {
+        Globals.efl_object_init();
+    }
+
+    public static void Shutdown()
+    {
+        Globals.efl_object_shutdown();
+    }
+}
+
+public interface IWrapper
+{
+    IntPtr raw_handle
+    {
+        get;
+    }
+    IntPtr raw_klass
+    {
+        get;
+    }
+}
+
+public interface IOwnershipTag
+{
+}
+
+public class OwnTag : IOwnershipTag
+{
+}
+
+public class NonOwnTag : IOwnershipTag
+{
+}
+
+public class MarshalTest<T, U> : ICustomMarshaler
+    where U : IOwnershipTag
+{
+    public static ICustomMarshaler GetInstance(string cookie)
+    {
+        eina.Log.Debug("MarshalTest.GetInstace cookie " + cookie);
+        return new MarshalTest<T, U>();
+    }
+    public void CleanUpManagedData(object ManagedObj)
+    {
+        //eina.Log.Warning("MarshalTest.CleanUpManagedData not implemented");
+        //throw new NotImplementedException();
+    }
+
+    public void CleanUpNativeData(IntPtr pNativeData)
+    {
+        //eina.Log.Warning("MarshalTest.CleanUpNativeData not implemented");
+        //throw new NotImplementedException();
+    }
+
+    public int GetNativeDataSize()
+    {
+        eina.Log.Debug("MarshalTest.GetNativeDataSize");
+        return 0;
+        //return 8;
+    }
+
+    public IntPtr MarshalManagedToNative(object ManagedObj)
+    {
+        eina.Log.Debug("MarshalTest.MarshallManagedToNative");
+        var r = ((IWrapper)ManagedObj).raw_handle;
+        if (typeof(U) == typeof(OwnTag))
+            efl.eo.Globals.efl_ref(r);
+        return r;
+    }
+
+    public object MarshalNativeToManaged(IntPtr pNativeData)
+    {
+        eina.Log.Debug("MarshalTest.MarshalNativeToManaged");
+        if (typeof(U) != typeof(OwnTag))
+            efl.eo.Globals.efl_ref(pNativeData);
+        return Activator.CreateInstance(typeof(T), new System.Object[] {pNativeData});
+//        return null;
+    }
+}
+
+public class StringPassOwnershipMarshaler : ICustomMarshaler {
+    public object MarshalNativeToManaged(IntPtr pNativeData) {
+        var ret = eina.StringConversion.NativeUtf8ToManagedString(pNativeData);
+        eina.MemoryNative.Free(pNativeData);
+        return ret;
+    }
+
+    public IntPtr MarshalManagedToNative(object managedObj) {
+        return eina.MemoryNative.StrDup((string)managedObj);
+    }
+
+    public void CleanUpNativeData(IntPtr pNativeData) {
+        // No need to cleanup. C will take care of it.
+    }
+
+    public void CleanUpManagedData(object managedObj) {
+    }
+
+    public int GetNativeDataSize() {
+        return -1;
+    }
+
+    public static ICustomMarshaler GetInstance(string cookie) {
+        if (marshaler == null) {
+            marshaler = new StringPassOwnershipMarshaler();
+        }
+        return marshaler;
+    }
+    static private StringPassOwnershipMarshaler marshaler;
+}
+
+public class StringKeepOwnershipMarshaler: ICustomMarshaler {
+    public object MarshalNativeToManaged(IntPtr pNativeData) {
+        return eina.StringConversion.NativeUtf8ToManagedString(pNativeData);
+    }
+
+    public IntPtr MarshalManagedToNative(object managedObj) {
+        return eina.StringConversion.ManagedStringToNativeUtf8Alloc((string)managedObj);
+    }
+
+    public void CleanUpNativeData(IntPtr pNativeData) {
+        // No need to free. The Native side will keep the ownership.
+    }
+
+    public void CleanUpManagedData(object managedObj) {
+    }
+
+    public int GetNativeDataSize() {
+        return -1;
+    }
+
+    public static ICustomMarshaler GetInstance(string cookie) {
+        if (marshaler == null) {
+            marshaler = new StringKeepOwnershipMarshaler();
+        }
+        return marshaler;
+    }
+    static private StringKeepOwnershipMarshaler marshaler;
+}
+
+public class StringsharePassOwnershipMarshaler : ICustomMarshaler {
+    public object MarshalNativeToManaged(IntPtr pNativeData) {
+        var ret = eina.StringConversion.NativeUtf8ToManagedString(pNativeData);
+        eina.Stringshare.eina_stringshare_del(pNativeData);
+        return ret;
+    }
+
+    public IntPtr MarshalManagedToNative(object managedObj) {
+        return eina.Stringshare.eina_stringshare_add((string)managedObj);
+    }
+
+    public void CleanUpNativeData(IntPtr pNativeData) {
+        // No need to free as it's for own() parameters.
+    }
+
+    public void CleanUpManagedData(object managedObj) {
+    }
+
+    public int GetNativeDataSize() {
+        return -1;
+    }
+
+    public static ICustomMarshaler GetInstance(string cookie) {
+        if (marshaler == null) {
+            marshaler = new StringsharePassOwnershipMarshaler();
+        }
+        return marshaler;
+    }
+    static private StringsharePassOwnershipMarshaler marshaler;
+}
+
+public class StringshareKeepOwnershipMarshaler : ICustomMarshaler {
+    public object MarshalNativeToManaged(IntPtr pNativeData) {
+        return eina.StringConversion.NativeUtf8ToManagedString(pNativeData);
+    }
+
+    public IntPtr MarshalManagedToNative(object managedObj) {
+        return eina.Stringshare.eina_stringshare_add((string)managedObj);
+    }
+
+    public void CleanUpNativeData(IntPtr pNativeData) {
+        // No need to free, as the native side will keep ownership.
+    }
+
+    public void CleanUpManagedData(object managedObj) {
+    }
+
+    public int GetNativeDataSize() {
+        return -1;
+    }
+
+    public static ICustomMarshaler GetInstance(string cookie) {
+        if (marshaler == null) {
+            marshaler = new StringshareKeepOwnershipMarshaler();
+        }
+        return marshaler;
+    }
+    static private StringshareKeepOwnershipMarshaler marshaler;
+}
+
+} // namespace eo
+
+public class EflException : Exception
+{
+    public EflException(string message) : base(message)
+    {
+    }
+}
+
+} // namespace efl
diff --git a/src/bindings/mono/eo_mono/object.cs b/src/bindings/mono/eo_mono/object.cs
new file mode 100644 (file)
index 0000000..08e1e5f
--- /dev/null
@@ -0,0 +1,10 @@
+
+namespace efl {
+
+using System;
+    
+// public interface Object : efl.eo.IWrapper
+// {
+// }
+    
+}
diff --git a/src/bindings/mono/eo_mono/workaround.cs b/src/bindings/mono/eo_mono/workaround.cs
new file mode 100644 (file)
index 0000000..7e338de
--- /dev/null
@@ -0,0 +1,523 @@
+
+using System;
+using System.Runtime.InteropServices;
+using System.Collections.Generic;
+
+[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
+public struct ClassDescription
+{
+    public uint version;
+    [MarshalAs(UnmanagedType.LPStr)] public String name;
+    public int class_type;
+    public UIntPtr data_size;
+    public IntPtr class_initializer;
+    public IntPtr class_constructor;
+    public IntPtr class_destructor;
+}
+
+[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
+public struct Efl_Op_Description
+{
+    public IntPtr api_func;
+    public IntPtr func;
+}
+
+[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
+public struct Efl_Object_Ops
+{
+    public IntPtr descs; /**< The op descriptions array of size count. */
+    public UIntPtr count; /**< Number of op descriptions. */
+};
+
+[StructLayout(LayoutKind.Sequential)]
+public struct EolianPD
+{
+    public IntPtr pointer;
+}
+
+#pragma warning disable 0169
+public struct Evas_Object_Box_Layout
+{
+    IntPtr o;
+    IntPtr priv;
+    IntPtr user_data;
+};
+[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
+public struct Evas_Object_Box_Data
+{
+}
+public delegate void Eina_Free_Cb(IntPtr data);
+public struct Evas_Object_Box_Option {
+    IntPtr obj;
+    [MarshalAsAttribute(UnmanagedType.U1)] bool max_reached;
+    [MarshalAsAttribute(UnmanagedType.U1)] bool min_reached;
+    evas.Coord alloc_size;
+};
+#pragma warning restore 0169
+
+namespace efl { namespace kw_event {
+
+[StructLayout(LayoutKind.Sequential)]
+public struct Description {
+    IntPtr pointer; // Opaque type, just pass the pointer. What about hot/freeze/etc?
+
+    private static Dictionary<string, IntPtr> descriptions = new Dictionary<string, IntPtr>();
+
+    public Description(string name)
+    {
+        if (!descriptions.ContainsKey(name))
+        {
+            IntPtr data = efl.eo.Globals.dlsym(efl.eo.Globals.RTLD_DEFAULT, name);
+
+            if (data == IntPtr.Zero) {
+                string error = eina.StringConversion.NativeUtf8ToManagedString(efl.eo.Globals.dlerror());
+                throw new Exception(error);
+            }
+            descriptions.Add(name, data);
+        }
+
+        this.pointer = descriptions[name];
+    }
+};
+
+} // namespace kw_event
+
+
+public delegate void Event_Cb(System.IntPtr data, ref Event evt);
+#pragma warning disable 0169
+public struct Callback_Array_Item {
+    IntPtr desc;
+    IntPtr func;
+};
+public struct Dbg_Info {
+    IntPtr name;
+    IntPtr value;
+};
+#pragma warning restore 0169
+
+namespace text {
+
+namespace cursor {
+
+[StructLayout(LayoutKind.Sequential)]
+public struct Cursor {
+    IntPtr obj;
+    UIntPtr pos; // UIntPtr to automatically change size_t between 32/64
+    IntPtr node;
+    [MarshalAsAttribute(UnmanagedType.U1)]bool changed;
+}
+
+} // namespace cursor
+
+namespace annotate {
+
+[StructLayout(LayoutKind.Sequential)]
+public struct Annotation {
+    IntPtr list;
+    IntPtr obj;
+    IntPtr start_node;
+    IntPtr end_node;
+    [MarshalAsAttribute(UnmanagedType.U1)]bool is_item;
+}
+
+} // namespace annotate
+
+} // namespace text
+
+public delegate void Signal_Cb(IntPtr data, IntPtr obj, IntPtr emission, IntPtr source);
+
+
+namespace gfx {
+
+public interface Buffer {}
+
+namespace buffer {
+public struct Access_Mode {}
+}
+        
+} // namespace gfx
+
+namespace access {
+
+public struct State_Set {
+    private ulong mask;
+
+    public static implicit operator State_Set(ulong x)
+    {
+        return new State_Set{mask=x};
+    }
+    public static implicit operator ulong(State_Set x)
+    {
+        return x.mask;
+    }
+}
+
+public struct Relation_Set {
+    private IntPtr mask;
+
+    public static implicit operator Relation_Set(IntPtr x)
+    {
+        return new Relation_Set{mask=x};
+    }
+    public static implicit operator IntPtr(Relation_Set x)
+    {
+        return x.mask;
+    }
+}
+
+public struct Action_Data {
+    public IntPtr name;
+    public IntPtr action;
+    public IntPtr param;
+    public IntPtr func;
+}
+
+} // namespace access
+
+namespace font {
+
+public struct Size {
+    private int mask;
+
+    public static implicit operator Size(int x)
+    {
+        return new Size{mask=x};
+    }
+    public static implicit operator int(Size x)
+    {
+        return x.mask;
+    }
+}
+
+}
+
+} // namespace efl
+
+namespace evas { namespace font {
+
+}
+
+
+// C# does not allow typedefs, so we use these implicit conversions.
+public struct Modifier_Mask {
+    private ulong mask;
+
+    public static implicit operator Modifier_Mask(ulong x)
+    {
+        return new Modifier_Mask{mask=x};
+    }
+    public static implicit operator ulong(Modifier_Mask x)
+    {
+        return x.mask;
+    }
+}
+
+public struct Coord {
+    int val;
+
+    public Coord(int value) { val = value; }
+    static public implicit operator Coord(int val) {
+        return new Coord(val);
+    }
+    static public implicit operator int(Coord coord) {
+        return coord.val;
+    }
+}
+
+
+}
+
+public struct Efl_Font_Size {
+    int val;
+
+    public Efl_Font_Size(int value) { val = value; }
+    static public implicit operator Efl_Font_Size(int val) {
+        return new Efl_Font_Size(val);
+    }
+    static public implicit operator int(Efl_Font_Size coord) {
+        return coord.val;
+    }
+}
+
+namespace eina {
+
+public struct Rectangle {
+    public int x;
+    public int y;
+    public int w;
+    public int h;
+}
+
+}
+
+namespace eina {
+
+public interface File {}
+
+}
+
+namespace evas {
+
+/* Copied from Evas_Legacy.h */
+public enum Text_Style_Type
+{
+   Plain = 0, /**< plain, standard text */
+   Shadow, /**< text with shadow underneath */
+   Outline, /**< text with an outline */
+   SoftOutline, /**< text with a soft outline */
+   Glow, /**< text with a glow effect */
+   OutlineShadow, /**< text with both outline and shadow effects */
+   FarShadow, /**< text with (far) shadow underneath */
+   OutlineSoftShadow, /**< text with outline and soft shadow effects combined */
+   SoftShadow, /**< text with (soft) shadow underneath */
+   FarSoftShadow, /**< text with (far soft) shadow underneath */
+
+   // Shadow direction modifiers
+   ShadowDirectionBottomRight = 0 /* 0 >> 4 */, /**< shadow growing to bottom right */
+   ShadowDirectionBottom= 16 /* 1 >> 4 */, /**< shadow growing to the bottom */
+   ShadowDirectionBottomLeft = 32 /* 2 >> 4 */, /**< shadow growing to bottom left */
+   ShadowDirectionLeft = 48 /* 3 >> 4 */, /**< shadow growing to the left */
+   ShadowDirectionTopLeft = 64 /* 4 >> 4 */, /**< shadow growing to top left */
+   ShadowDirectionTop = 80 /* 5 >> 4 */, /**< shadow growing to the top */
+   ShadowDirectionTopRight = 96 /* 6 >> 4 */, /**< shadow growing to top right */
+   ShadowDirectionRight = 112 /* 7 >> 4 */ /**< shadow growing to the right */
+};
+    
+
+// Copied from Evas_Common.h
+//
+//
+//
+
+public enum Callback_Type
+{
+  EVAS_CALLBACK_MOUSE_IN = 0, /**< Mouse In Event */
+  EVAS_CALLBACK_MOUSE_OUT, /**< Mouse Out Event */
+  EVAS_CALLBACK_MOUSE_DOWN, /**< Mouse Button Down Event */
+  EVAS_CALLBACK_MOUSE_UP, /**< Mouse Button Up Event */
+  EVAS_CALLBACK_MOUSE_MOVE, /**< Mouse Move Event */
+  EVAS_CALLBACK_MOUSE_WHEEL, /**< Mouse Wheel Event */
+  EVAS_CALLBACK_MULTI_DOWN, /**< Multi-touch Down Event */
+  EVAS_CALLBACK_MULTI_UP, /**< Multi-touch Up Event */
+  EVAS_CALLBACK_MULTI_MOVE, /**< Multi-touch Move Event */
+  EVAS_CALLBACK_FREE, /**< Object Being Freed (Called after Del) */
+  EVAS_CALLBACK_KEY_DOWN, /**< Key Press Event */
+  EVAS_CALLBACK_KEY_UP, /**< Key Release Event */
+  EVAS_CALLBACK_FOCUS_IN, /**< Focus In Event */
+  EVAS_CALLBACK_FOCUS_OUT, /**< Focus Out Event */
+  EVAS_CALLBACK_SHOW, /**< Show Event */
+  EVAS_CALLBACK_HIDE, /**< Hide Event */
+  EVAS_CALLBACK_MOVE, /**< Move Event */
+  EVAS_CALLBACK_RESIZE, /**< Resize Event */
+  EVAS_CALLBACK_RESTACK, /**< Restack Event */
+  EVAS_CALLBACK_DEL, /**< Object Being Deleted (called before Free) */
+  EVAS_CALLBACK_HOLD, /**< Events go on/off hold */
+  EVAS_CALLBACK_CHANGED_SIZE_HINTS, /**< Size hints changed event */
+  EVAS_CALLBACK_IMAGE_PRELOADED, /**< Image has been preloaded */
+  EVAS_CALLBACK_CANVAS_FOCUS_IN, /**< Canvas got focus as a whole */
+  EVAS_CALLBACK_CANVAS_FOCUS_OUT, /**< Canvas lost focus as a whole */
+  EVAS_CALLBACK_RENDER_FLUSH_PRE, /**< Called after render update regions have
+                                   * been calculated, but only if update regions exist */
+  EVAS_CALLBACK_RENDER_FLUSH_POST, /**< Called after render update regions have
+                                    * been sent to the display server, but only
+                                    * if update regions existed for the most recent frame */
+  EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN, /**< Canvas object got focus */
+  EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_OUT, /**< Canvas object lost focus */
+  EVAS_CALLBACK_IMAGE_UNLOADED, /**< Image data has been unloaded (by some mechanism in Evas that throw out original image data) */
+  EVAS_CALLBACK_RENDER_PRE, /**< Called just before rendering starts on the canvas target. @since 1.2 */
+  EVAS_CALLBACK_RENDER_POST, /**< Called just after rendering stops on the canvas target. @since 1.2 */
+  EVAS_CALLBACK_IMAGE_RESIZE, /**< Image size is changed. @since 1.8 */
+  EVAS_CALLBACK_DEVICE_CHANGED, /**< Devices added, removed or changed on canvas. @since 1.8 */
+  EVAS_CALLBACK_AXIS_UPDATE, /**< Input device changed value on some axis. @since 1.13 */
+  EVAS_CALLBACK_CANVAS_VIEWPORT_RESIZE, /**< Canvas viewport resized. @since 1.15 */
+  EVAS_CALLBACK_LAST /**< Sentinel value to indicate last enum field during
+                      * iteration */
+};
+
+}
+
+namespace elm {
+
+namespace atspi {
+public struct State_Set {
+    private ulong val;
+
+    public static implicit operator State_Set(ulong x)
+    {
+        return new State_Set{val=x};
+    }
+    public static implicit operator ulong(State_Set x)
+    {
+        return x.val;
+    }
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct Relation_Set
+{
+    public IntPtr pointer; // list<ptr(elm.atspi.Relation)>
+}
+} // namespace atspi
+
+namespace gengrid { namespace item {
+[StructLayout(LayoutKind.Sequential)]
+public struct Class
+{
+    int version;
+    uint refcount;
+    [MarshalAsAttribute(UnmanagedType.U1)]bool delete_me;
+    IntPtr item_style;
+    IntPtr decorate_item_style;
+    IntPtr decorate_all_item_style;
+
+    // Delegates inside Elm_Gen_Item_Class_Functions
+    IntPtr text_get;
+    IntPtr content_get;
+    IntPtr state_get;
+    IntPtr del;
+    IntPtr filter_get;
+    IntPtr reusable_content_get;
+}
+} // namespace item
+} // namespace gengrid
+
+namespace genlist { namespace item {
+[StructLayout(LayoutKind.Sequential)]
+public struct Class
+{
+    int version;
+    uint refcount;
+    [MarshalAsAttribute(UnmanagedType.U1)]bool delete_me;
+    IntPtr item_style;
+    IntPtr decorate_item_style;
+    IntPtr decorate_all_item_style;
+
+    // Delegates inside Elm_Gen_Item_Class_Functions
+    IntPtr text_get;
+    IntPtr content_get;
+    IntPtr state_get;
+    IntPtr del;
+    IntPtr filter_get;
+    IntPtr reusable_content_get;
+}
+} // namespace item
+} // namespace genlist
+
+} // namespace elm
+
+// Global delegates
+public delegate IntPtr list_data_get_func_type(IntPtr l);
+public delegate void region_hook_func_type(IntPtr data, IntPtr obj);
+public delegate void slider_freefunc_type(IntPtr data);
+public delegate void slider_func_type(double val);
+
+public delegate int Eina_Compare_Cb(IntPtr a, IntPtr b);
+public delegate void Elm_Interface_Scrollable_Cb(IntPtr obj, IntPtr data);
+public delegate void Elm_Interface_Scrollable_Min_Limit_Cb(IntPtr obj,
+                                                     [MarshalAsAttribute(UnmanagedType.U1)]bool w,
+                                                     [MarshalAsAttribute(UnmanagedType.U1)]bool h);
+public delegate void Elm_Interface_Scrollable_Resize_Cb(IntPtr obj, evas.Coord w, evas.Coord h);
+public delegate void Elm_Entry_Item_Provider_Cb(IntPtr data, IntPtr obj, IntPtr item);
+public delegate void Elm_Entry_Filter_Cb(IntPtr data, IntPtr obj, IntPtr text);
+[return: MarshalAsAttribute(UnmanagedType.U1)]
+public delegate bool Elm_Multibuttonentry_Item_Filter_Cb(IntPtr obj, IntPtr item_label, IntPtr item_data, IntPtr data);
+public delegate IntPtr Elm_Multibuttonentry_Format_Cb(int count, IntPtr data);
+[return: MarshalAsAttribute(UnmanagedType.U1)]
+public delegate bool Elm_Fileselector_Filter_Func(IntPtr path, [MarshalAsAttribute(UnmanagedType.U1)]bool dir, IntPtr data);
+public delegate void Evas_Smart_Cb(IntPtr data, IntPtr obj, IntPtr event_info);
+public delegate void Elm_Gesture_Event_Cb(IntPtr data, IntPtr event_info);
+public delegate void Elm_Object_Item_Signal_Cb(IntPtr data, IntPtr item, IntPtr emission, IntPtr source);
+public delegate void Elm_Tooltip_Item_Content_Cb(IntPtr data, IntPtr obj, IntPtr tooltip, IntPtr item);
+public delegate void Elm_Sys_Notify_Send_Cb(IntPtr data, uint id);
+public delegate IntPtr Elm_Calendar_Format_Cb(IntPtr format);
+
+namespace edje {
+
+public delegate void Signal_Cb(IntPtr data, IntPtr obj, IntPtr emission, IntPtr source);
+public delegate void Markup_Filter_Cb(IntPtr data, IntPtr obj, IntPtr part, IntPtr text );
+public delegate void Item_Provider_Cb(IntPtr data, IntPtr obj, IntPtr part, IntPtr item);
+// Message_Handler_Cb is now legacy
+
+namespace text {
+public delegate void Filter_Cb(IntPtr data, IntPtr obj, IntPtr part, int _type, IntPtr text);
+public delegate void Change_Cb(IntPtr data, IntPtr obj, IntPtr part);
+}
+
+
+} // namespace edje
+
+[StructLayout(LayoutKind.Sequential)]
+public struct Elm_Code
+{
+    IntPtr file;
+    IntPtr widgets;
+    IntPtr parsers;
+
+    // Below is inside _Elm_Code_Config
+    [MarshalAsAttribute(UnmanagedType.U1)]bool config;
+}
+
+[StructLayout(LayoutKind.Sequential)]
+public struct Elm_Code_Line
+{
+    IntPtr file;
+    IntPtr content;
+    uint length;
+    uint number;
+    IntPtr modified;
+
+    Elm_Code_Status_Type status;
+    IntPtr tokens;
+
+    IntPtr data;
+    IntPtr status_text;
+}
+
+public enum Elm_Code_Status_Type {
+   ELM_CODE_STATUS_TYPE_DEFAULT = 0,
+   ELM_CODE_STATUS_TYPE_CURRENT,
+   ELM_CODE_STATUS_TYPE_IGNORED,
+   ELM_CODE_STATUS_TYPE_NOTE,
+   ELM_CODE_STATUS_TYPE_WARNING,
+   ELM_CODE_STATUS_TYPE_ERROR,
+   ELM_CODE_STATUS_TYPE_FATAL,
+
+   ELM_CODE_STATUS_TYPE_ADDED,
+   ELM_CODE_STATUS_TYPE_REMOVED,
+   ELM_CODE_STATUS_TYPE_CHANGED,
+
+   ELM_CODE_STATUS_TYPE_PASSED,
+   ELM_CODE_STATUS_TYPE_FAILED,
+
+   ELM_CODE_STATUS_TYPE_TODO,
+
+   ELM_CODE_STATUS_TYPE_COUNT
+};
+
+
+[StructLayout(LayoutKind.Sequential)]
+public struct Elm_Atspi_Action
+{
+    IntPtr name;
+    IntPtr action;
+    IntPtr param;
+    IntPtr func;
+}
+
+// Some places stil use the non-namespaced Efl_Event_Cb
+public delegate void Efl_Event_Cb(System.IntPtr data, ref efl.Event evt);
+
+[StructLayout(LayoutKind.Sequential)]
+public struct Tm {
+    int tm_sec;
+    int tm_min;
+    int tm_hour;
+    int tm_mday;
+    int tm_mon;
+    int tm_year;
+    int tm_wday;
+    int tm_yday;
+    int tm_isdst;
+}
+
+public delegate IntPtr Efl_Ui_Calendar_Format_Cb(Tm stime); // struct tm as argument