dotnet plugin: Switch to P/Invoke.
authorFlorian Forster <octo@leeloo.lan.home.verplant.org>
Fri, 3 Dec 2010 10:17:48 +0000 (11:17 +0100)
committerFlorian Forster <octo@collectd.org>
Thu, 5 Apr 2012 08:22:02 +0000 (10:22 +0200)
This is easier since most of the marshaling is done by the CLR.

Thanks to "ki9a" from the #mono IRC channel for his help with this!

bindings/csharp/collectd.cs
bindings/csharp/test.cs
src/dotnet.c

index bc09267..279f430 100644 (file)
 using System;
 using System.Collections;
 using System.Text;
-using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
 
 namespace CollectdAPI
 {
-  public interface IRead /* {{{ */
-  {
-    int read ();
-  } /* }}} interface IRead */
-
-  public class Collectd /* {{{ */
-  {
-    [MethodImplAttribute(MethodImplOptions.InternalCall)]
-      public extern static int log (int severity, string message);
-
-    [MethodImplAttribute(MethodImplOptions.InternalCall)]
-      public extern static int registerRead (string name, IRead obj);
-
-    [MethodImplAttribute(MethodImplOptions.InternalCall)]
-      public extern static int dispatchValues (ValueList vl);
-  } /* }}} class Collectd */
+  public delegate int CollectdReadCallback ();
 
-  public abstract class Value /* {{{ */
+  public interface IValue /* {{{ */
   {
-    public abstract long toLong ();
-    public abstract double toDouble ();
-  } /* }}} class Value */
+    long ToLong ();
+    double ToDouble ();
+  } /* }}} class IValue */
 
-  public class gaugeValue: Value /* {{{ */
+  public class GaugeValue: IValue /* {{{ */
   {
     private double _value;
 
-    public gaugeValue (double v)
+    public GaugeValue (double v)
     {
       this._value = v;
     }
 
-    public override long toLong () { return ((long) this._value); }
-    public override double toDouble () { return (this._value); }
+    public long ToLong () { return ((long) this._value); }
+    public double ToDouble () { return (this._value); }
 
     public override string ToString ()
     {
       return (this._value.ToString ());
     }
-  } /* }}} class gaugeValue */
+  } /* }}} class GaugeValue */
 
-  public class deriveValue: Value /* {{{ */
+  public class DeriveValue: IValue /* {{{ */
   {
     private long _value;
 
-    public deriveValue (long v)
+    public DeriveValue (long v)
     {
       this._value = v;
     }
 
-    public override long toLong () { return (this._value); }
-    public override double toDouble () { return ((double) this._value); }
+    public long ToLong () { return (this._value); }
+    public double ToDouble () { return ((double) this._value); }
 
     public override string ToString ()
     {
       return (this._value.ToString ());
     }
-  } /* }}} class deriveValue */
+  } /* }}} class DeriveValue */
 
   public class Identifier /* {{{ */
   {
+    [MarshalAs (UnmanagedType.LPStr)]
     protected string _host;
+    [MarshalAs (UnmanagedType.LPStr)]
     protected string _plugin;
+    [MarshalAs (UnmanagedType.LPStr)]
     protected string _pluginInstance;
+    [MarshalAs (UnmanagedType.LPStr)]
     protected string _type;
+    [MarshalAs (UnmanagedType.LPStr)]
     protected string _typeInstance;
 
     public Identifier (string host,
@@ -118,17 +108,77 @@ namespace CollectdAPI
       this._typeInstance   = id._typeInstance;
     } /* Identifier() */
 
-    public string getHost           () { return (this._host);           }
-    public string getPlugin         () { return (this._plugin);         }
-    public string getPluginInstance () { return (this._pluginInstance); }
-    public string getType           () { return (this._type);           }
-    public string getTypeInstance   () { return (this._typeInstance);   }
+    public string Host /* {{{ */
+    {
+      get
+      {
+        return (this._host);
+      }
+      set
+      {
+        if ((value == null) || (value.Length < 1))
+          throw new ArgumentException ();
+        this._host = value;
+      }
+    } /* }}} */
 
-    public void setHost           (string s) { this._host           = s; }
-    public void setPlugin         (string s) { this._plugin         = s; }
-    public void setPluginInstance (string s) { this._pluginInstance = s; }
-    public void setType           (string s) { this._type           = s; }
-    public void setTypeInstance   (string s) { this._typeInstance   = s; }
+    public string Plugin /* {{{ */
+    {
+      get
+      {
+        return (this._plugin);
+      }
+      set
+      {
+        if ((value == null) || (value.Length < 1))
+          throw new ArgumentException ();
+        this._plugin = value;
+      }
+    } /* }}} string Plugin */
+
+    public string PluginInstance /* {{{ */
+    {
+      get
+      {
+        return (this._pluginInstance);
+      }
+      set
+      {
+        if (value == null)
+          this._pluginInstance = "";
+        else
+          this._pluginInstance = value;
+      }
+    } /* }}} string PluginInstance */
+
+    public string Type /* {{{ */
+    {
+      get
+      {
+        return (this._type);
+      }
+      set
+      {
+        if ((value == null) || (value.Length < 1))
+          throw new ArgumentException ();
+        this._type = value;
+      }
+    } /* }}} string Type */
+
+    public string TypeInstance /* {{{ */
+    {
+      get
+      {
+        return (this._typeInstance);
+      }
+      set
+      {
+        if (value == null)
+          this._typeInstance = "";
+        else
+          this._typeInstance = value;
+      }
+    } /* }}} string TypeInstance */
 
     public override string ToString ()
     {
@@ -158,7 +208,7 @@ namespace CollectdAPI
     {
       this._interval = 10.0;
       this._values = new ArrayList ();
-      this.setTime (DateTime.Now);
+      this._time = 0.0;
     }
 
     public ValueList (ValueList vl)
@@ -169,43 +219,53 @@ namespace CollectdAPI
       this._time     = vl._time;
     }
 
-    public IList getValues ()
+    public IList GetValues ()
     {
       return (this._values);
     }
 
-    public void setValues (IList values)
+    public void SetValues (IList values)
     {
       this._values = new ArrayList (values);
     }
 
-    public void addValue (Value v)
+    public void AddValue (IValue v)
     {
       this._values.Add (v);
     }
 
-    public void clearValues ()
+    public void ClearValues ()
     {
       this._values.Clear ();
     }
 
-    public double getInterval ()
-    {
-      return (this._interval);
-    }
-
-    public void setInterval (double interval)
+    public double Interval
     {
-      if (interval > 0.0)
-        this._interval = interval;
+      get
+      {
+        return (this._interval);
+      }
+      set
+      {
+        if (value > 0.0)
+          this._interval = value;
+      }
     }
 
-    public double getTime ()
+    public double Time
     {
-      return (this._time);
+      get
+      {
+        return (this._time);
+      }
+      set
+      {
+        if (value >= 0.0)
+          this._time = value;
+      }
     }
 
-    public void setTime (DateTime dt)
+    public void SetTime (DateTime dt)
     {
       DateTime dtBase = new DateTime (1970,1,1,0,0,0);
       TimeSpan tsDiff = dt.ToUniversalTime () - dtBase;
@@ -213,12 +273,6 @@ namespace CollectdAPI
       this._time = (double) tsDiff.TotalSeconds;
     }
 
-    public void setTime (double t)
-    {
-      if (t > 0.0)
-        this._time = t;
-    }
-
     public override string ToString ()
     {
       StringBuilder sb = new StringBuilder ("{");
@@ -239,6 +293,116 @@ namespace CollectdAPI
       return (sb.ToString ());
     } /* string ToString */
   } /* }}} class ValueList */
+
+  [StructLayout (LayoutKind.Explicit)]
+  struct value_u /* {{{ */
+  {
+    /* Emulate a union */
+    [FieldOffset (0)] public double gauge;
+    [FieldOffset (0)] public long   derive;
+  } /* }}} struct value_u */
+
+  [StructLayout (LayoutKind.Sequential)]
+  struct value_list_s /* {{{ */
+  {
+    public value_u[] values;
+    public int values_num;
+    public double time;
+    public double interval;
+    [MarshalAs(UnmanagedType.LPStr)]
+    public string host;
+    [MarshalAs(UnmanagedType.LPStr)]
+    public string plugin;
+    [MarshalAs(UnmanagedType.LPStr)]
+    public string plugin_instance;
+    [MarshalAs(UnmanagedType.LPStr)]
+    public string type;
+    [MarshalAs(UnmanagedType.LPStr)]
+    public string type_instance;
+
+    public value_list_s (ValueList vl)
+    {
+      IList values = vl.GetValues ();
+
+      this.values_num = values.Count;
+      this.values = new value_u[this.values_num];
+      for (int i = 0; i < values.Count; i++)
+      {
+        IValue v = values[i] as IValue;
+
+        if (v is GaugeValue)
+          this.values[i].gauge = v.ToDouble ();
+        else
+          this.values[i].derive = v.ToLong ();
+      }
+      this.time = vl.Time;
+      this.interval = vl.Interval;
+
+      this.host = vl.Host;
+      this.plugin = vl.Plugin;
+      this.plugin_instance = vl.PluginInstance;
+      this.type = vl.Type;
+      this.type_instance = vl.TypeInstance;
+    }
+  } /* }}} struct value_list_s */
+
+  public class Collectd /* {{{ */
+  {
+    private static Hashtable _readFunctions = new Hashtable ();
+
+    [DllImport("__Internal", EntryPoint="plugin_log")]
+    private extern static int _log (
+        [MarshalAs(UnmanagedType.SysInt)] int severity,
+        [MarshalAs(UnmanagedType.LPStr)]  string message);
+
+    [DllImport("__Internal", EntryPoint="dotnet_register_read")]
+    private extern static int _registerRead (
+        [MarshalAs(UnmanagedType.LPStr)] string name,
+        CollectdReadCallback func);
+
+    [DllImport("__Internal", EntryPoint="dotnet_dispatch_values")]
+    private extern static int _dispatchValues (value_list_s vl);
+
+    public static int DispatchValues (ValueList vl)
+    {
+      return (_dispatchValues (new value_list_s (vl)));
+    }
+
+    public static int LogError (string message)
+    {
+      return (_log (3, message));
+    }
+
+    public static int LogWarning (string message)
+    {
+      return (_log (4, message));
+    }
+
+    public static int LogNotice (string message)
+    {
+      return (_log (5, message));
+    }
+
+    public static int LogInfo (string message)
+    {
+      return (_log (6, message));
+    }
+
+    public static int LogDebug (string message)
+    {
+      return (_log (7, message));
+    }
+
+    public static int RegisterRead (string name, CollectdReadCallback func)
+    {
+      if (_readFunctions.Contains (name))
+        return (-1);
+      _readFunctions.Add (name, func);
+
+      return (_registerRead (name, func));
+    }
+  } /* }}} class Collectd */
+
 }
 
 /* vim: set sw=2 sts=2 et fdm=marker : */
index 6e56326..374f93c 100644 (file)
@@ -1,29 +1,24 @@
 using CollectdAPI;
 
-public class EmbedTest: IRead
+public class EmbedTest
 {
        public EmbedTest ()
        {
-               System.Console.WriteLine ("EmbedTest ();");
-               Collectd.registerRead ("EmbedTest::read", this);
+               Collectd.LogInfo ("EmbedTest plugin: Initializing the module.");
+               Collectd.RegisterRead ("EmbedTest", new CollectdReadCallback (read));
        }
 
        public int read ()
        {
-               ValueList vl = new ValueList ("host", "plugin", "pinst", "type", "tinst");
+               ValueList vl = new ValueList ("localhost", "dotnet", "", "gauge", "test");
 
-               vl.setInterval (10.0);
-               vl.addValue (new gaugeValue (3.1337));
+               vl.Interval = 10.0;
+               vl.AddValue (new GaugeValue (31337));
 
-               System.Console.WriteLine ("vl: " + vl);
+               Collectd.LogDebug ("vl: " + vl);
 
-               Collectd.dispatchValues (vl);
+               Collectd.DispatchValues (vl);
                return (0);
        }
-
-       public static void Main()
-       {
-               System.Console.WriteLine("Hello, World!");
-       }
 }
 
index 71b548c..73240a8 100644 (file)
 #include <mono/metadata/assembly.h>
 #include <mono/metadata/threads.h>
 
-struct dotnet_callback_info_s
+struct dotnet_value_list_s
 {
-  gint32 domain_id;
-  guint32 obj_handle;
+  value_t *values;
+  int values_len;
+  double time;
+  double interval;
+  char *host;
+  char *plugin;
+  char *plugin_instance;
+  char *type;
+  char *type_instance;
 };
-typedef struct dotnet_callback_info_s dotnet_callback_info_t;
+typedef struct dotnet_value_list_s dotnet_value_list_t;
+
+typedef int (*dotnet_read_cb) (void);
 
 static MonoDomain *_domain = NULL;
 
 static int dotnet_read (user_data_t *ud) /* {{{ */
 {
-  dotnet_callback_info_t *ci = ud->data;
-  MonoDomain *domain;
-  MonoThread *thread;
-  MonoClass  *class;
-  MonoObject *object;
-  MonoMethod *method;
-  MonoObject *ret;
-
-  DEBUG ("dotnet plugin: mono_domain_get_by_id (%"PRIi32") ...",
-      (int32_t) ci->domain_id);
-  domain = mono_domain_get_by_id (ci->domain_id);
-  if (domain == NULL)
-  {
-    ERROR ("dotnet plugin: mono_domain_get_by_id failed.");
-    return (-1);
-  }
-
-  thread = mono_thread_attach (domain);
-  if (thread == NULL)
-  {
-    ERROR ("dotnet plugin: mono_thread_attach failed.");
-    return (-1);
-  }
-
-  if (!mono_domain_set (domain, /* force = */ 0))
-  {
-    ERROR ("dotnet plugin: mono_domain_set failed.");
-    return (-1);
-  }
-
-  DEBUG ("dotnet plugin: mono_gchandle_get_target ...");
-  object = mono_gchandle_get_target (ci->obj_handle);
-  if (object == NULL)
-  {
-    ERROR ("dotnet plugin: mono_gchandle_get_target failed.");
-    mono_thread_detach (thread);
-    return (-1);
-  }
-
-  DEBUG ("dotnet plugin: mono_object_get_class ...");
-  class = mono_object_get_class (object);
-  if (class == NULL)
-  {
-    ERROR ("dotnet plugin: mono_object_get_class failed.");
-    mono_thread_detach (thread);
-    return (-1);
-  }
-
-  DEBUG ("dotnet plugin: mono_class_get_method_from_name ...");
-  method = mono_class_get_method_from_name (class,
-      /* name = */ "read", /* nargs = */ 0);
-  if (method == NULL)
-  {
-    ERROR ("dotnet plugin: mono_class_get_method_from_name failed.");
-    mono_thread_detach (thread);
-    return (-1);
-  }
+  dotnet_read_cb cb = ud->data;
 
-  DEBUG ("dotnet plugin: mono_runtime_invoke ...");
-  ret = mono_runtime_invoke (method, object, /* params = */ NULL,
-      /* exception ptr = */ NULL);
-  DEBUG ("dotnet plugin: mono_runtime_invoke returned %p.", (void *) ret);
-
-  mono_thread_detach (thread);
-  return (0);
+  return ((*cb) ());
 } /* }}} int dotnet_read */
 
-static void dotnet_callback_info_free (void *ptr) /* {{{ */
-{
-  dotnet_callback_info_t *ci = ptr;
-
-  if (ci == NULL)
-    return;
-
-  mono_gchandle_free (ci->obj_handle);
-  sfree (ci);
-} /* }}} void dotnet_callback_info_free */
-
-static MonoMethod *dotnet_object_method_get_from_name (MonoObject *object, /* {{{ */
-    const char *name, int param_count)
-{
-  MonoClass *class;
-
-  class = mono_object_get_class (object);
-  if (class == NULL)
-    return (NULL);
-
-  while (42)
-  {
-    MonoClass *pclass;
-    MonoMethod *method;
-
-    method = mono_class_get_method_from_name (class, name, param_count);
-    if (method != NULL)
-      return (method);
-
-    pclass = mono_class_get_parent (class);
-    if ((pclass == NULL) || (pclass == class))
-    {
-      ERROR ("dotnet plugin: Unable to find method \"%s\" in class \"%s\".",
-          name, mono_class_get_name (mono_object_get_class (object)));
-      return (NULL);
-    }
-    class = pclass;
-  } /* while (42) */
-  /* Not reached */
-  return (NULL);
-} /* }}} MonoMethod *dotnet_object_method_get_from_name */
-
-static MonoProperty *dotnet_object_get_property_from_name (MonoObject *object, /* {{{ */
-    const char *name)
-{
-  MonoClass *class;
-
-  class = mono_object_get_class (object);
-
-  while (42)
-  {
-    MonoClass *pclass;
-    MonoProperty *prop;
-
-    prop = mono_class_get_property_from_name (class, name);
-    if (prop != NULL)
-      return (prop);
-
-    pclass = mono_class_get_parent (class);
-    if ((pclass == NULL) || (pclass == class))
-    {
-      ERROR ("dotnet plugin: Unable to find property \"%s\" in class \"%s\".",
-          name, mono_class_get_name (mono_object_get_class (object)));
-      return (NULL);
-    }
-    class = pclass;
-  } /* while (42) */
-  /* Not reached */
-  return (NULL);
-} /* }}} MonoProperty *dotnet_object_get_property_from_name */
-
-static int dotnet_object_method_get_string (MonoObject *obj, /* {{{ */
-    const char *method_name, char *buffer, size_t buffer_size)
-{
-  MonoMethod *method;
-  MonoObject *ret;
-  char *tmp;
-
-  method = dotnet_object_method_get_from_name (obj, method_name, /* nargs = */ 0);
-  if (method == NULL)
-    return (-1);
-
-  ret = mono_runtime_invoke (method, obj, /* params = */ NULL, /* exception = */ NULL);
-  if (ret == NULL)
-    return (-2);
-
-  tmp = mono_string_to_utf8 ((MonoString *) ret);
-  if (tmp == NULL)
-  {
-    ERROR ("dotnet plugin: mono_string_to_utf8 failed.");
-    return (-3);
-  }
-  DEBUG ("dotnet plugin: Method \"%s\" returned string \"%s\".",
-      mono_method_get_name (method), tmp);
-
-  sstrncpy (buffer, tmp, buffer_size);
-  return (0);
-} /* }}} int dotnet_object_method_get_string */
-
-static int dotnet_object_method_get_cdtime (MonoObject *obj, /* {{{ */
-    const char *method_name, cdtime_t *ret_value)
-{
-  MonoMethod *method;
-  MonoObject *ret_obj;
-  double tmp;
-
-  method = dotnet_object_method_get_from_name (obj, method_name, /* nargs = */ 0);
-  if (method == NULL)
-    return (-1);
-
-  ret_obj = mono_runtime_invoke (method, obj, /* params = */ NULL, /* exception = */ NULL);
-  if (ret_obj == NULL)
-    return (-2);
-
-  tmp = *((double *) mono_object_unbox (ret_obj));
-  DEBUG ("dotnet plugin: Method \"%s\" returned value %.3f.",
-      mono_method_get_name (method), tmp);
-  *ret_value = DOUBLE_TO_CDTIME_T (tmp);
-
-  return (0);
-} /* }}} int dotnet_object_method_get_cdtime */
-
-static int dotnet_object_method_get_values (MonoObject *obj, /* {{{ */
-    value_list_t *vl)
-{
-  MonoMethod *method;
-  MonoObject *ilist_obj;
-  MonoObject *tmp_obj;
-  MonoProperty *count_prop;
-  MonoProperty *item_prop;
-  int32_t i;
-
-  method = dotnet_object_method_get_from_name (obj, "getValues", /* nargs = */ 0);
-  if (method == NULL)
-    return (-1);
-
-  ilist_obj = mono_runtime_invoke (method, obj, /* params = */ NULL, /* exception = */ NULL);
-  if (ilist_obj == NULL)
-    return (-2);
-
-  count_prop = dotnet_object_get_property_from_name (ilist_obj, "Count");
-  if (count_prop == NULL)
-  {
-    ERROR ("dotnet plugin: dotnet_object_get_property_from_name (\"Count\") failed.");
-    return (-4);
-  }
-
-  item_prop = dotnet_object_get_property_from_name (ilist_obj, "Item");
-  if (item_prop == NULL)
-  {
-    ERROR ("dotnet plugin: dotnet_object_get_property_from_name (\"Item\") failed.");
-    return (-5);
-  }
-
-  method = mono_property_get_get_method (count_prop);
-  tmp_obj = mono_runtime_invoke (method, ilist_obj, /* params = */ NULL, /* exception = */ NULL);
-  if (tmp_obj == NULL)
-  {
-    ERROR ("dotnet plugin: mono_runtime_invoke failed.");
-    return (-6);
-  }
-  DEBUG ("dotnet plugin: Type of the Count property is \"%s\".",
-      mono_class_get_name (mono_object_get_class (tmp_obj)));
-
-  vl->values_len = (int) *((int32_t *) mono_object_unbox (tmp_obj));
-  DEBUG ("dotnet plugin: vl->values_len = %i;", vl->values_len);
-
-  if (vl->values_len <= 0)
-  {
-    vl->values_len = 0;
-    return (-7);
-  }
-
-  vl->values = calloc ((size_t) vl->values_len, sizeof (*vl->values));
-  if (vl->values == NULL)
-  {
-    vl->values_len = 0;
-    return (-8);
-  }
-
-  for (i = 0; i < ((int32_t) vl->values_len); i++)
-  {
-    void *args[2] = { &i, NULL };
-    MonoObject *value_obj;
-    const char *class_name;
-
-    method = mono_property_get_get_method (item_prop);
-    value_obj = mono_runtime_invoke (method, ilist_obj, /* params = */ args, /* exception = */ NULL);
-    if (value_obj == NULL)
-    {
-      ERROR ("dotnet plugin: Item(%i) failed.", i);
-      return (-7);
-    }
-
-    class_name = mono_class_get_name (mono_object_get_class (value_obj));
-    if (strcmp ("gaugeValue", class_name) == 0)
-    {
-      MonoObject *gauge_obj;
-
-      method = dotnet_object_method_get_from_name (value_obj, "toDouble", /* nargs = */ 0);
-      if (method == NULL)
-        return (-9);
-
-      gauge_obj = mono_runtime_invoke (method, value_obj, /* args = */ NULL, /* exception = */ NULL);
-      if (gauge_obj == NULL)
-        return (-10);
-
-      vl->values[i].gauge = (gauge_t) *((double *) mono_object_unbox (gauge_obj));
-      DEBUG ("dotnet plugin: Gauge value %"PRIi32" = %g;",
-          i, vl->values[i].gauge);
-    }
-    else if (strcmp ("deriveValue", class_name) == 0)
-    {
-      MonoObject *derive_obj;
-
-      method = dotnet_object_method_get_from_name (value_obj, "toLong", /* nargs = */ 0);
-      if (method == NULL)
-        return (-9);
-
-      derive_obj = mono_runtime_invoke (method, value_obj, /* args = */ NULL, /* exception = */ NULL);
-      if (derive_obj == NULL)
-        return (-10);
-
-      vl->values[i].derive = (derive_t) *((int64_t *) mono_object_unbox (derive_obj));
-      DEBUG ("dotnet plugin: Derive value %"PRIi32" = %"PRIi64";",
-          i, vl->values[i].derive);
-    }
-  }
-
-  return (0);
-} /* }}} int dotnet_object_method_get_values */
-
 /*
  * Functions exposed to .Net
  */
-static int dotnet_log (int severity, MonoString *message) /* {{{ */
-{
-  char *tmp = mono_string_to_utf8 (message);
-
-  DEBUG ("dotnet_log (severity = %i, message = \"%s\");", severity, tmp);
-
-  return (0);
-} /* }}} int dotnet_log */
-
-static int dotnet_register_read (MonoString *name, MonoObject *obj) /* {{{ */
+int dotnet_register_read (const char *name, dotnet_read_cb cb) /* {{{ */
 {
   user_data_t ud;
-  dotnet_callback_info_t *ci;
 
-  MonoClass *class;
-  MonoMethod *method;
-
-  /* Sanity checks: Make sure this object actually has the required method. */
-  class = mono_object_get_class (obj);
-  if (class == NULL)
-  {
-    ERROR ("dotnet plugin: mono_object_get_class failed.");
-    return (-1);
-  }
-
-  method = mono_class_get_method_from_name (class,
-      /* name = */ "read", /* param count = */ 0);
-  if (method == NULL)
-  {
-    ERROR ("dotnet plugin: mono_class_get_method_from_name failed.");
-    return (-1);
-  }
-
-  ci = malloc (sizeof (*ci));
-  if (ci == NULL)
-  {
-    ERROR ("dotnet plugin: malloc failed.");
-    return (-1);
-  }
-  memset (ci, 0, sizeof (*ci));
-
-  ci->domain_id = mono_domain_get_id (mono_domain_get ());
-  ci->obj_handle = mono_gchandle_new (obj, /* pinned = */ 1);
-
-  ud.data = ci;
-  ud.free_func = dotnet_callback_info_free;
+  memset (&ud, 0, sizeof (ud));
+  ud.data = cb;
+  ud.free_func = NULL;
 
   plugin_register_complex_read (/* group = */ "dotnet",
-      /* name      = */ mono_string_to_utf8 (name),
+      /* name      = */ name,
       /* callback  = */ dotnet_read,
       /* interval  = */ NULL,
       /* user data = */ &ud);
@@ -403,47 +79,30 @@ static int dotnet_register_read (MonoString *name, MonoObject *obj) /* {{{ */
   return (0);
 } /* }}} int dotnet_register_read */
 
-static int dotnet_dispatch_values (MonoObject *obj) /* {{{ */
+int dotnet_dispatch_values (dotnet_value_list_t *dvl) /* {{{ */
 {
   value_list_t vl = VALUE_LIST_INIT;
-  int status;
 
-  status = dotnet_object_method_get_string (obj, "getHost", vl.host, sizeof (vl.host));
-  if (status != 0)
-    return (status);
+  vl.values = dvl->values;
+  vl.values_len = dvl->values_len;
 
-  status = dotnet_object_method_get_string (obj, "getPlugin", vl.plugin, sizeof (vl.plugin));
-  if (status != 0)
-    return (status);
+  if (dvl->time > 0.0)
+    vl.time = DOUBLE_TO_CDTIME_T (dvl->time);
+  else
+    vl.interval = 0;
 
-  status = dotnet_object_method_get_string (obj, "getPluginInstance", vl.plugin_instance, sizeof (vl.plugin_instance));
-  if (status != 0)
-    return (status);
+  if (dvl->interval > 0.0)
+    vl.interval = DOUBLE_TO_CDTIME_T (dvl->interval);
+  else
+    vl.interval = interval_g;
 
-  status = dotnet_object_method_get_string (obj, "getType", vl.type, sizeof (vl.type));
-  if (status != 0)
-    return (status);
-
-  status = dotnet_object_method_get_string (obj, "getTypeInstance", vl.type_instance, sizeof (vl.type_instance));
-  if (status != 0)
-    return (status);
-
-  status = dotnet_object_method_get_cdtime (obj, "getInterval", &vl.interval);
-  if (status != 0)
-    return (status);
+  sstrncpy (vl.host, dvl->host, sizeof (vl.host));
+  sstrncpy (vl.plugin, dvl->plugin, sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, dvl->plugin_instance, sizeof (vl.plugin_instance));
+  sstrncpy (vl.type, dvl->type, sizeof (vl.type));
+  sstrncpy (vl.type_instance, dvl->type_instance, sizeof (vl.type_instance));
 
-  status = dotnet_object_method_get_cdtime (obj, "getTime", &vl.time);
-  if (status != 0)
-    return (status);
-
-  status = dotnet_object_method_get_values (obj, &vl);
-  if (status != 0)
-    return (status);
-
-  status = plugin_dispatch_values (&vl);
-  sfree (vl.values);
-
-  return (status);
+  return (plugin_dispatch_values (&vl));
 } /* }}} int dotnet_dispatch_values */
 
 /*
@@ -610,10 +269,6 @@ void module_register (void)
     return;
   }
 
-  mono_add_internal_call ("CollectdAPI.Collectd::log", dotnet_log);
-  mono_add_internal_call ("CollectdAPI.Collectd::registerRead", dotnet_register_read);
-  mono_add_internal_call ("CollectdAPI.Collectd::dispatchValues", dotnet_dispatch_values);
-
   plugin_register_complex_config ("dotnet", dotnet_config);
 } /* void module_register */