libgaim/plugins/mono/loader/signal-glue.c

branch
gaim
changeset 20470
77693555855f
parent 11980
fe5c2c58508c
parent 14254
77edc7a6191a
child 20471
1966704b3e42
equal deleted inserted replaced
13071:b98e72d4089a 20470:77693555855f
1 #include "mono-glue.h"
2 #include "mono-helper.h"
3 #include "debug.h"
4 #include "blist.h"
5 #include "signals.h"
6 #include "value.h"
7
8 typedef struct {
9 MonoObject *func;
10 char *signal;
11 GaimValue **values;
12 GaimValue *ret_value;
13 int num_vals;
14 } SignalData;
15
16 static GaimCallback get_callback(SignalData *sig_data);
17
18 static gpointer dispatch_callback(SignalData *sig_data, int num_vals, ...)
19 {
20 MonoArray *array;
21 MonoObject *obj;
22 int i;
23 gpointer meth_args[1];
24 gpointer gaim_obj;
25
26 va_list args;
27
28 va_start(args, num_vals);
29
30 array = mono_array_new(ml_get_domain(), mono_get_object_class(), num_vals);
31
32 for (i = 0; i < num_vals; i++) {
33 if (gaim_value_get_type(sig_data->values[i]) == GAIM_TYPE_SUBTYPE) {
34 gaim_obj = va_arg(args, gpointer);
35 obj = ml_object_from_gaim_subtype(gaim_value_get_subtype(sig_data->values[i]), gaim_obj);
36 mono_array_set(array, MonoObject*, i, obj);
37 } else {
38 gaim_obj = va_arg(args, gpointer);
39 obj = ml_object_from_gaim_type(gaim_value_get_type(sig_data->values[i]), gaim_obj);
40 mono_array_set(array, MonoObject*, i, obj);
41 }
42 }
43
44 va_end(args);
45
46 meth_args[0] = array;
47
48 return ml_delegate_invoke(sig_data->func, meth_args);
49 }
50
51 static void cb_void__pointer(void *arg1, void *data)
52 {
53 dispatch_callback((SignalData*)data, ((SignalData*)data)->num_vals, arg1);
54 }
55
56 static void cb_void__pointer_pointer_pointer(void *arg1, void *arg2, void *arg3, void *data)
57 {
58 dispatch_callback((SignalData*)data, ((SignalData*)data)->num_vals, arg1, arg2, arg3);
59 }
60
61
62 int gaim_signal_connect_glue(MonoObject* h, MonoObject *plugin, MonoString *signal, MonoObject *func)
63 {
64 char *sig;
65 void **instance = NULL;
66 SignalData *sig_data;
67 GaimMonoPlugin *mplug;
68 MonoClass *klass;
69
70 sig = mono_string_to_utf8(signal);
71 gaim_debug(GAIM_DEBUG_INFO, "mono", "connecting signal: %s\n", sig);
72
73 instance = (void*)mono_object_unbox(h);
74
75 sig_data = g_new0(SignalData, 1);
76
77 sig_data->func = func;
78 sig_data->signal = sig;
79
80 gaim_signal_get_values(*instance, sig, &sig_data->ret_value, &sig_data->num_vals, &sig_data->values);
81
82 klass = mono_object_get_class(plugin);
83
84 mplug = ml_find_plugin_by_class(klass);
85
86 mplug->signal_data = g_list_append(mplug->signal_data, (gpointer)sig_data);
87
88 return gaim_signal_connect(*instance, sig, (gpointer)klass, get_callback(sig_data), (gpointer)sig_data);
89 }
90
91 static int determine_index(GaimType type)
92 {
93 switch (type) {
94 case GAIM_TYPE_SUBTYPE:
95 case GAIM_TYPE_STRING:
96 case GAIM_TYPE_OBJECT:
97 case GAIM_TYPE_POINTER:
98 case GAIM_TYPE_BOXED:
99 return 1;
100 break;
101 default:
102 return type;
103 break;
104 }
105 }
106
107 static gpointer callbacks[]= {
108 NULL,
109 cb_void__pointer,
110 NULL,
111 cb_void__pointer_pointer_pointer
112 };
113
114 static int callbacks_array_size = sizeof(callbacks) / sizeof(GaimCallback);
115
116
117 static GaimCallback get_callback(SignalData *sig_data)
118 {
119 int i, index = 0;
120
121 if (sig_data->ret_value == NULL)
122 index = 0;
123 else
124 index = determine_index(gaim_value_get_type(sig_data->ret_value));
125
126 for (i = 0; i < sig_data->num_vals; i++) {
127 index += determine_index(gaim_value_get_type(sig_data->values[i]));
128 }
129
130 gaim_debug(GAIM_DEBUG_INFO, "mono", "get_callback index = %d\n", index);
131
132 if (index >= callbacks_array_size || callbacks[index] == NULL) {
133 gaim_debug(GAIM_DEBUG_ERROR, "mono", "couldn't find a callback function for signal: %s\n", sig_data->signal);
134 return NULL;
135 }
136
137 gaim_debug(GAIM_DEBUG_MISC, "mono", "using callback at index: %d\n", index);
138 return GAIM_CALLBACK(callbacks[index]);
139 }

mercurial