| |
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 } |