--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libgaim/plugins/mono/loader/mono-helper.c Sun Apr 15 02:10:37 2007 +0000 @@ -0,0 +1,251 @@ +/* + * Mono Plugin Loader + * + * -- Thanks to the perl plugin loader for all the great tips ;-) + * + * Eoin Coffey + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <glib.h> +#include <string.h> +#include "mono-helper.h" +#include "mono-glue.h" +#include "value.h" +#include "debug.h" + +static gboolean _runtime_active = FALSE; + +gboolean ml_init() +{ + MonoDomain *d; + + g_return_val_if_fail(_runtime_active == FALSE, TRUE); + + d = mono_jit_init("gaim"); + + if (!d) { + ml_set_domain(NULL); + return FALSE; + } + + ml_set_domain(d); + + ml_init_internal_calls(); + + _runtime_active = TRUE; + + return TRUE; +} + +void ml_uninit() +{ + g_return_if_fail(_runtime_active == TRUE); + + mono_jit_cleanup(ml_get_domain()); + + ml_set_domain(NULL); + + _runtime_active = FALSE; +} + +MonoObject* ml_delegate_invoke(MonoObject *method, void **params) +{ + MonoObject *ret, *exception; + + ret = mono_runtime_delegate_invoke(method, params, &exception); + if (exception) { + gaim_debug(GAIM_DEBUG_ERROR, "mono", "caught exception: %s\n", mono_class_get_name(mono_object_get_class(exception))); + } + + return ret; +} + +MonoObject* ml_invoke(MonoMethod *method, void *obj, void **params) +{ + MonoObject *ret, *exception; + + ret = mono_runtime_invoke(method, obj, params, &exception); + if (exception) { + gaim_debug(GAIM_DEBUG_ERROR, "mono", "caught exception: %s\n", mono_class_get_name(mono_object_get_class(exception))); + } + + return ret; +} + +MonoClass* ml_find_plugin_class(MonoImage *image) +{ + MonoClass *klass, *pklass = NULL; + int i, total; + + total = mono_image_get_table_rows (image, MONO_TABLE_TYPEDEF); + for (i = 1; i <= total; ++i) { + klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | i); + pklass = mono_class_get_parent(klass); + if (pklass) + if (strcmp("GaimPlugin", mono_class_get_name(pklass)) == 0) + return klass; + } + + return NULL; +} + +void ml_set_prop_string(MonoObject *obj, char *field, char *data) +{ + MonoClass *klass; + MonoProperty *prop; + MonoString *str; + gpointer args[1]; + + klass = mono_object_get_class(obj); + + prop = mono_class_get_property_from_name(klass, field); + + str = mono_string_new(ml_get_domain(), data); + + args[0] = str; + + mono_property_set_value(prop, obj, args, NULL); +} + +gchar* ml_get_prop_string(MonoObject *obj, char *field) +{ + MonoClass *klass; + MonoProperty *prop; + MonoString *str; + + klass = mono_object_get_class(obj); + + prop = mono_class_get_property_from_name(klass, field); + + str = (MonoString*)mono_property_get_value(prop, obj, NULL, NULL); + + return mono_string_to_utf8(str); +} + +gboolean ml_is_api_dll(MonoImage *image) +{ + MonoClass *klass; + int i, total; + + total = mono_image_get_table_rows (image, MONO_TABLE_TYPEDEF); + for (i = 1; i <= total; ++i) { + klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | i); + if (strcmp(mono_class_get_name(klass), "Debug") == 0) + if (strcmp(mono_class_get_namespace(klass), "Gaim") == 0) { + ml_set_api_image(image); + return TRUE; + } + } + + return FALSE; +} + +MonoObject* ml_object_from_gaim_type(GaimType type, gpointer data) +{ + return NULL; +} + +MonoObject* ml_object_from_gaim_subtype(GaimSubType type, gpointer data) +{ + MonoObject *obj = NULL; + + switch (type) { + case GAIM_SUBTYPE_BLIST_BUDDY: + obj = gaim_blist_build_buddy_object(data); + break; + case GAIM_SUBTYPE_STATUS: + obj = gaim_status_build_status_object(data); + break; + default: + break; + } + + return obj; +} + +MonoObject* ml_create_api_object(char *class_name) +{ + MonoObject *obj = NULL; + MonoClass *klass = NULL; + + klass = mono_class_from_name(ml_get_api_image(), "Gaim", class_name); + if (!klass) { + gaim_debug(GAIM_DEBUG_FATAL, "mono", "couldn't find the '%s' class\n", class_name); + return NULL; + } + + obj = mono_object_new(ml_get_domain(), klass); + if (!obj) { + gaim_debug(GAIM_DEBUG_FATAL, "mono", "couldn't create the object from class '%s'\n", class_name); + return NULL; + } + + mono_runtime_object_init(obj); + + return obj; +} + +static MonoDomain *_domain = NULL; + +MonoDomain* ml_get_domain(void) +{ + return _domain; +} + +void ml_set_domain(MonoDomain *d) +{ + _domain = d; +} + +static MonoImage *_api_image = NULL; + +void ml_set_api_image(MonoImage *image) +{ + _api_image = image; +} + +MonoImage* ml_get_api_image() +{ + return _api_image; +} + +void ml_init_internal_calls(void) +{ + mono_add_internal_call("Gaim.Debug::_debug", gaim_debug_glue); + mono_add_internal_call("Gaim.Signal::_connect", gaim_signal_connect_glue); + mono_add_internal_call("Gaim.BuddyList::_get_handle", gaim_blist_get_handle_glue); +} + +static GHashTable *plugins_hash = NULL; + +void ml_add_plugin(GaimMonoPlugin *plugin) +{ + if (!plugins_hash) + plugins_hash = g_hash_table_new(NULL, NULL); + + g_hash_table_insert(plugins_hash, plugin->klass, plugin); +} + +gboolean ml_remove_plugin(GaimMonoPlugin *plugin) +{ + return g_hash_table_remove(plugins_hash, plugin->klass); +} + +gpointer ml_find_plugin(GaimMonoPlugin *plugin) +{ + return g_hash_table_lookup(plugins_hash, plugin->klass); +} + +gpointer ml_find_plugin_by_class(MonoClass *klass) +{ + return g_hash_table_lookup(plugins_hash, klass); +} + +GHashTable* ml_get_plugin_hash() +{ + return plugins_hash; +}