+/*
+ * mono-dl.c: Interface to the dynamic linker
+ *
+ * Author:
+ * Mono Team (http://www.mono-project.com)
+ *
+ * Copyright 2001-2004 Ximian, Inc.
+ * Copyright 2004-2009 Novell, Inc.
+ */
#include "config.h"
#include "mono/utils/mono-dl.h"
+#include "mono/utils/mono-embed.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <glib.h>
-#ifdef PLATFORM_WIN32
+#ifdef TARGET_WIN32
#define SOPREFIX ""
static const char suffixes [][5] = {
".dll"
".so",
".bundle"
};
+#elif EMBEDDED_PINVOKE
+#define SOPREFIX ""
+static const char suffixes [][1] = {
+ ""
+};
#else
#define SOPREFIX "lib"
static const char suffixes [][4] = {
};
#endif
-#ifdef PLATFORM_WIN32
+#ifdef TARGET_WIN32
#include <windows.h>
#include <psapi.h>
return lflags;
}
+#elif EMBEDDED_PINVOKE
+#define SO_HANDLE_TYPE void*
+void *LL_SO_OPEN (const char *file, int flags);
+int LL_SO_CLOSE (void *handle);
+#define LL_SO_SYMBOL(module,symbol) _LL_SO_SYMBOL((module)->handle, (symbol))
+void *_LL_SO_SYMBOL (void *handle, const char *symbol);
+char *LL_SO_ERROR();
+#define LL_SO_TRFLAGS(flags) 0
+
#else
/* no dynamic loader supported */
#define SO_HANDLE_TYPE void*
int main_module;
};
-#ifdef PLATFORM_WIN32
+#ifdef TARGET_WIN32
static char*
w32_dlerror (void)
* from the module to the shared namespace. The MONO_DL_LAZY bit can be set
* to lazily load the symbols instead of resolving everithing at load time.
* @error_msg points to a string where an error message will be stored in
- * case of failure.
+ * case of failure. The error must be released with g_free.
*
* Returns: a MonoDl pointer on success, NULL on failure.
*/
module->main_module = name == NULL? TRUE: FALSE;
lib = LL_SO_OPEN (name, lflags);
if (!lib) {
+ char *lname;
+ char *llname;
+ const char *suff;
+ const char *ext;
/* This platform does not support dlopen */
- if (name == NULL)
+ if (name == NULL) {
+ free (module);
return NULL;
+ }
- char *lname;
- char *llname;
- const char *suff = ".la";
- const char *ext = strrchr (name, '.');
+ suff = ".la";
+ ext = strrchr (name, '.');
if (ext && strcmp (ext, ".la") == 0)
suff = "";
lname = g_strconcat (name, suff, NULL);
int idx;
const char *prefix;
const char *suffix;
+ gboolean first_call;
int prlen;
+ int suffixlen;
char *res;
+
if (!iter)
return NULL;
+
+ /*
+ The first time we are called, idx = 0 (as *iter is initialized to NULL). This is our
+ "bootstrap" phase in which we check the passed name verbatim and only if we fail to find
+ the dll thus named, we start appending suffixes, each time increasing idx twice (since now
+ the 0 value became special and we need to offset idx to a 0-based array index). This is
+ done to handle situations when mapped dll name is specified as libsomething.so.1 or
+ libsomething.so.1.1 or libsomething.so - testing it algorithmically would be an overkill
+ here.
+ */
idx = GPOINTER_TO_UINT (*iter);
- if (idx >= G_N_ELEMENTS (suffixes))
- return NULL;
+ if (idx == 0) {
+ first_call = TRUE;
+ suffix = "";
+ suffixlen = 0;
+ } else {
+ idx--;
+ if (idx >= G_N_ELEMENTS (suffixes))
+ return NULL;
+ first_call = FALSE;
+ suffix = suffixes [idx];
+ suffixlen = strlen (suffix);
+ }
prlen = strlen (SOPREFIX);
if (prlen && strncmp (name, SOPREFIX, prlen) != 0)
prefix = SOPREFIX;
else
prefix = "";
- /* if the platform prefix is already provided, we suppose the caller knows the full name already */
- if (prlen && strncmp (name, SOPREFIX, prlen) == 0)
+
+ if (first_call || (suffixlen && strstr (name, suffix) == (name + strlen (name) - suffixlen)))
suffix = "";
- else
- suffix = suffixes [idx];
+
if (directory && *directory)
- res = g_strconcat (directory, G_DIR_SEPARATOR_S, prefix, name, suffixes [idx], NULL);
+ res = g_strconcat (directory, G_DIR_SEPARATOR_S, prefix, name, suffix, NULL);
else
- res = g_strconcat (prefix, name, suffixes [idx], NULL);
+ res = g_strconcat (prefix, name, suffix, NULL);
++idx;
+ if (!first_call)
+ idx++;
*iter = GUINT_TO_POINTER (idx);
return res;
}
+#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