| 1 /* |
|
| 2 * Mono Plugin Loader |
|
| 3 * |
|
| 4 * -- Thanks to the perl plugin loader for all the great tips ;-) |
|
| 5 * |
|
| 6 * Eoin Coffey |
|
| 7 */ |
|
| 8 |
|
| 9 #ifdef HAVE_CONFIG_H |
|
| 10 #include <config.h> |
|
| 11 #endif |
|
| 12 |
|
| 13 #include <glib.h> |
|
| 14 #include <string.h> |
|
| 15 #include "mono-helper.h" |
|
| 16 #include "mono-glue.h" |
|
| 17 #include "value.h" |
|
| 18 #include "debug.h" |
|
| 19 |
|
| 20 static gboolean _runtime_active = FALSE; |
|
| 21 |
|
| 22 gboolean ml_init() |
|
| 23 { |
|
| 24 MonoDomain *d; |
|
| 25 |
|
| 26 g_return_val_if_fail(_runtime_active == FALSE, TRUE); |
|
| 27 |
|
| 28 d = mono_jit_init("gaim"); |
|
| 29 |
|
| 30 if (!d) { |
|
| 31 ml_set_domain(NULL); |
|
| 32 return FALSE; |
|
| 33 } |
|
| 34 |
|
| 35 ml_set_domain(d); |
|
| 36 |
|
| 37 ml_init_internal_calls(); |
|
| 38 |
|
| 39 _runtime_active = TRUE; |
|
| 40 |
|
| 41 return TRUE; |
|
| 42 } |
|
| 43 |
|
| 44 void ml_uninit() |
|
| 45 { |
|
| 46 g_return_if_fail(_runtime_active == TRUE); |
|
| 47 |
|
| 48 mono_jit_cleanup(ml_get_domain()); |
|
| 49 |
|
| 50 ml_set_domain(NULL); |
|
| 51 |
|
| 52 _runtime_active = FALSE; |
|
| 53 } |
|
| 54 |
|
| 55 MonoObject* ml_delegate_invoke(MonoObject *method, void **params) |
|
| 56 { |
|
| 57 MonoObject *ret, *exception; |
|
| 58 |
|
| 59 ret = mono_runtime_delegate_invoke(method, params, &exception); |
|
| 60 if (exception) { |
|
| 61 gaim_debug(GAIM_DEBUG_ERROR, "mono", "caught exception: %s\n", mono_class_get_name(mono_object_get_class(exception))); |
|
| 62 } |
|
| 63 |
|
| 64 return ret; |
|
| 65 } |
|
| 66 |
|
| 67 MonoObject* ml_invoke(MonoMethod *method, void *obj, void **params) |
|
| 68 { |
|
| 69 MonoObject *ret, *exception; |
|
| 70 |
|
| 71 ret = mono_runtime_invoke(method, obj, params, &exception); |
|
| 72 if (exception) { |
|
| 73 gaim_debug(GAIM_DEBUG_ERROR, "mono", "caught exception: %s\n", mono_class_get_name(mono_object_get_class(exception))); |
|
| 74 } |
|
| 75 |
|
| 76 return ret; |
|
| 77 } |
|
| 78 |
|
| 79 MonoClass* ml_find_plugin_class(MonoImage *image) |
|
| 80 { |
|
| 81 MonoClass *klass, *pklass = NULL; |
|
| 82 int i, total; |
|
| 83 |
|
| 84 total = mono_image_get_table_rows (image, MONO_TABLE_TYPEDEF); |
|
| 85 for (i = 1; i <= total; ++i) { |
|
| 86 klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | i); |
|
| 87 pklass = mono_class_get_parent(klass); |
|
| 88 if (pklass) |
|
| 89 if (strcmp("GaimPlugin", mono_class_get_name(pklass)) == 0) |
|
| 90 return klass; |
|
| 91 } |
|
| 92 |
|
| 93 return NULL; |
|
| 94 } |
|
| 95 |
|
| 96 void ml_set_prop_string(MonoObject *obj, char *field, char *data) |
|
| 97 { |
|
| 98 MonoClass *klass; |
|
| 99 MonoProperty *prop; |
|
| 100 MonoString *str; |
|
| 101 gpointer args[1]; |
|
| 102 |
|
| 103 klass = mono_object_get_class(obj); |
|
| 104 |
|
| 105 prop = mono_class_get_property_from_name(klass, field); |
|
| 106 |
|
| 107 str = mono_string_new(ml_get_domain(), data); |
|
| 108 |
|
| 109 args[0] = str; |
|
| 110 |
|
| 111 mono_property_set_value(prop, obj, args, NULL); |
|
| 112 } |
|
| 113 |
|
| 114 gchar* ml_get_prop_string(MonoObject *obj, char *field) |
|
| 115 { |
|
| 116 MonoClass *klass; |
|
| 117 MonoProperty *prop; |
|
| 118 MonoString *str; |
|
| 119 |
|
| 120 klass = mono_object_get_class(obj); |
|
| 121 |
|
| 122 prop = mono_class_get_property_from_name(klass, field); |
|
| 123 |
|
| 124 str = (MonoString*)mono_property_get_value(prop, obj, NULL, NULL); |
|
| 125 |
|
| 126 return mono_string_to_utf8(str); |
|
| 127 } |
|
| 128 |
|
| 129 gboolean ml_is_api_dll(MonoImage *image) |
|
| 130 { |
|
| 131 MonoClass *klass; |
|
| 132 int i, total; |
|
| 133 |
|
| 134 total = mono_image_get_table_rows (image, MONO_TABLE_TYPEDEF); |
|
| 135 for (i = 1; i <= total; ++i) { |
|
| 136 klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | i); |
|
| 137 if (strcmp(mono_class_get_name(klass), "Debug") == 0) |
|
| 138 if (strcmp(mono_class_get_namespace(klass), "Gaim") == 0) { |
|
| 139 ml_set_api_image(image); |
|
| 140 return TRUE; |
|
| 141 } |
|
| 142 } |
|
| 143 |
|
| 144 return FALSE; |
|
| 145 } |
|
| 146 |
|
| 147 MonoObject* ml_object_from_gaim_type(GaimType type, gpointer data) |
|
| 148 { |
|
| 149 return NULL; |
|
| 150 } |
|
| 151 |
|
| 152 MonoObject* ml_object_from_gaim_subtype(GaimSubType type, gpointer data) |
|
| 153 { |
|
| 154 MonoObject *obj = NULL; |
|
| 155 |
|
| 156 switch (type) { |
|
| 157 case GAIM_SUBTYPE_BLIST_BUDDY: |
|
| 158 obj = gaim_blist_build_buddy_object(data); |
|
| 159 break; |
|
| 160 case GAIM_SUBTYPE_STATUS: |
|
| 161 obj = gaim_status_build_status_object(data); |
|
| 162 break; |
|
| 163 default: |
|
| 164 break; |
|
| 165 } |
|
| 166 |
|
| 167 return obj; |
|
| 168 } |
|
| 169 |
|
| 170 MonoObject* ml_create_api_object(char *class_name) |
|
| 171 { |
|
| 172 MonoObject *obj = NULL; |
|
| 173 MonoClass *klass = NULL; |
|
| 174 |
|
| 175 klass = mono_class_from_name(ml_get_api_image(), "Gaim", class_name); |
|
| 176 if (!klass) { |
|
| 177 gaim_debug(GAIM_DEBUG_FATAL, "mono", "couldn't find the '%s' class\n", class_name); |
|
| 178 return NULL; |
|
| 179 } |
|
| 180 |
|
| 181 obj = mono_object_new(ml_get_domain(), klass); |
|
| 182 if (!obj) { |
|
| 183 gaim_debug(GAIM_DEBUG_FATAL, "mono", "couldn't create the object from class '%s'\n", class_name); |
|
| 184 return NULL; |
|
| 185 } |
|
| 186 |
|
| 187 mono_runtime_object_init(obj); |
|
| 188 |
|
| 189 return obj; |
|
| 190 } |
|
| 191 |
|
| 192 static MonoDomain *_domain = NULL; |
|
| 193 |
|
| 194 MonoDomain* ml_get_domain(void) |
|
| 195 { |
|
| 196 return _domain; |
|
| 197 } |
|
| 198 |
|
| 199 void ml_set_domain(MonoDomain *d) |
|
| 200 { |
|
| 201 _domain = d; |
|
| 202 } |
|
| 203 |
|
| 204 static MonoImage *_api_image = NULL; |
|
| 205 |
|
| 206 void ml_set_api_image(MonoImage *image) |
|
| 207 { |
|
| 208 _api_image = image; |
|
| 209 } |
|
| 210 |
|
| 211 MonoImage* ml_get_api_image() |
|
| 212 { |
|
| 213 return _api_image; |
|
| 214 } |
|
| 215 |
|
| 216 void ml_init_internal_calls(void) |
|
| 217 { |
|
| 218 mono_add_internal_call("Gaim.Debug::_debug", gaim_debug_glue); |
|
| 219 mono_add_internal_call("Gaim.Signal::_connect", gaim_signal_connect_glue); |
|
| 220 mono_add_internal_call("Gaim.BuddyList::_get_handle", gaim_blist_get_handle_glue); |
|
| 221 } |
|
| 222 |
|
| 223 static GHashTable *plugins_hash = NULL; |
|
| 224 |
|
| 225 void ml_add_plugin(GaimMonoPlugin *plugin) |
|
| 226 { |
|
| 227 if (!plugins_hash) |
|
| 228 plugins_hash = g_hash_table_new(NULL, NULL); |
|
| 229 |
|
| 230 g_hash_table_insert(plugins_hash, plugin->klass, plugin); |
|
| 231 } |
|
| 232 |
|
| 233 gboolean ml_remove_plugin(GaimMonoPlugin *plugin) |
|
| 234 { |
|
| 235 return g_hash_table_remove(plugins_hash, plugin->klass); |
|
| 236 } |
|
| 237 |
|
| 238 gpointer ml_find_plugin(GaimMonoPlugin *plugin) |
|
| 239 { |
|
| 240 return g_hash_table_lookup(plugins_hash, plugin->klass); |
|
| 241 } |
|
| 242 |
|
| 243 gpointer ml_find_plugin_by_class(MonoClass *klass) |
|
| 244 { |
|
| 245 return g_hash_table_lookup(plugins_hash, klass); |
|
| 246 } |
|
| 247 |
|
| 248 GHashTable* ml_get_plugin_hash() |
|
| 249 { |
|
| 250 return plugins_hash; |
|
| 251 } |
|