+#if EMBEDDED_PINVOKE
+static GHashTable *mono_dls;
+static char *ll_last_error = "";
+
+/**
+ * mono_dl_register_library:
+ * @name: Library name, this is the name used by the DllImport as the external library name
+ * @mappings: the mappings to register for P/Invoke.
+ *
+ * This function is only available on builds that define
+ * EMBEDDED_PINVOKE, this is available for systems that do not provide
+ * a dynamic linker but still want to use DllImport to easily invoke
+ * code from the managed side into the unmanaged world.
+ *
+ * Mappings is a pointer to the first element of an array of
+ * MonoDlMapping values. The list must be terminated with both
+ * the name and addr fields set to NULL.
+ *
+ * This is typically used like this:
+ * MonoDlMapping sample_library_mappings [] = {
+ * { "CallMe", CallMe },
+ * { NULL, NULL }
+ * };
+ *
+ * ...
+ * main ()
+ * {
+ * ...
+ * mono_dl_register_library ("sample", sample_library_mappings);
+ * ...
+ * }
+ *
+ * Then the C# code can use this P/Invoke signature:
+ *
+ * [DllImport ("sample")]
+ * extern static int CallMe (int f);
+ */
+void
+mono_dl_register_library (const char *name, MonoDlMapping *mappings)
+{
+ if (mono_dls == NULL)
+ mono_dls = g_hash_table_new (g_str_hash, g_str_equal);
+
+ printf ("Inserting: 0x%p\n", mappings);
+ g_hash_table_insert (mono_dls, g_strdup (name), mappings);
+}
+
+void *
+LL_SO_OPEN (const char *file, int flag)
+{
+ void *mappings;
+
+ if (mono_dls == NULL){
+ ll_last_error = "Library not registered";
+ return NULL;
+ }
+
+ mappings = g_hash_table_lookup (mono_dls, file);
+ ll_last_error = mappings == NULL ? "File not registered" : "";
+ return mappings;
+}
+
+int LL_SO_CLOSE (void *handle)
+{
+ // No-op
+ return 0;
+}
+
+void *
+_LL_SO_SYMBOL (void *handle, const char *symbol)
+{
+ MonoDlMapping *mappings = (MonoDlMapping *) handle;
+
+ for (;mappings->name; mappings++){
+ if (strcmp (symbol, mappings->name) == 0){
+ ll_last_error = "";
+ return mappings->addr;
+ }
+ }
+ ll_last_error = "Symbol not found";
+ return NULL;
+}
+
+char *
+LL_SO_ERROR (void)
+{
+ return g_strdup (ll_last_error);
+}
+#endif