1
From e3fa476cf681d5e826d5b3494ef45e3daebf3cbf Mon Sep 17 00:00:00 2001
2
From: Colin Walters <walters@verbum.org>
3
Date: Wed, 21 Dec 2011 16:51:30 -0500
4
Subject: [PATCH 1/2] function: Correctly convert from ffi return values to
5
GIArgument on big-endian
7
ffi always returns a long value even if a function's return type is
8
e.g. guint8. We can't just directly give ffi_call a GIArgument to
9
store its return value because when the size of the return type is
10
smaller than long, it will write into the wrong address.
12
Instead cast the value at the C level.
14
Based on a patch from Ray Strode <rstrode@redhat.com>
16
https://bugzilla.gnome.org/show_bug.cgi?id=665152
18
gi/function.c | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
19
1 files changed, 123 insertions(+), 6 deletions(-)
21
diff --git a/gi/function.c b/gi/function.c
22
index ef644da..dcba849 100644
25
@@ -147,6 +147,61 @@ gjs_callback_trampoline_unref(GjsCallbackTrampoline *trampoline)
30
+set_return_ffi_arg_from_giargument (GITypeInfo *ret_type,
32
+ GIArgument *return_value)
34
+ switch (g_type_info_get_tag(ret_type)) {
35
+ case GI_TYPE_TAG_INT8:
36
+ *(ffi_sarg *) result = return_value->v_int8;
37
+ case GI_TYPE_TAG_UINT8:
38
+ *(ffi_arg *) result = return_value->v_uint8;
40
+ case GI_TYPE_TAG_INT16:
41
+ *(ffi_sarg *) result = return_value->v_int16;
43
+ case GI_TYPE_TAG_UINT16:
44
+ *(ffi_arg *) result = return_value->v_uint16;
46
+ case GI_TYPE_TAG_INT32:
47
+ *(ffi_sarg *) result = return_value->v_int32;
49
+ case GI_TYPE_TAG_UINT32:
50
+ case GI_TYPE_TAG_BOOLEAN:
51
+ case GI_TYPE_TAG_UNICHAR:
52
+ *(ffi_arg *) result = return_value->v_uint32;
55
+ case GI_TYPE_TAG_INT64:
56
+ *(ffi_sarg *) result = return_value->v_int64;
58
+ case GI_TYPE_TAG_UINT64:
59
+ *(ffi_arg *) result = return_value->v_uint64;
61
+ case GI_TYPE_TAG_INTERFACE:
63
+ GIBaseInfo* interface_info;
64
+ GIInfoType interface_type;
66
+ interface_info = g_type_info_get_interface(ret_type);
67
+ interface_type = g_base_info_get_type(interface_info);
69
+ switch (interface_type) {
70
+ case GI_INFO_TYPE_ENUM:
71
+ case GI_INFO_TYPE_FLAGS:
72
+ *(ffi_sarg *) result = return_value->v_long;
75
+ *(ffi_arg *) result = (ffi_arg) return_value->v_pointer;
80
+ *(ffi_arg *) result = (ffi_arg) return_value->v_pointer;
85
/* This is our main entry point for ffi_closure callbacks.
86
* ffi_prep_closure is doing pure magic and replaces the original
87
@@ -166,6 +221,7 @@ gjs_callback_closure(ffi_cif *cif,
88
int i, n_args, n_jsargs;
91
+ GArgument return_value;
92
gboolean success = FALSE;
95
@@ -215,10 +271,13 @@ gjs_callback_closure(ffi_cif *cif,
96
GJS_ARGUMENT_RETURN_VALUE,
105
+ set_return_ffi_arg_from_giargument(&ret_type, result, &return_value);
110
@@ -306,6 +365,61 @@ get_length_from_arg (GArgument *arg, GITypeTag tag)
114
+/* Extract the correct bits from an ffi_arg return value into
115
+ * GIArgument: https://bugzilla.gnome.org/show_bug.cgi?id=665152
118
+set_gargument_from_ffi_return_value (GITypeInfo *return_info,
119
+ GIArgument *return_value,
122
+ switch (g_type_info_get_tag (return_info)) {
123
+ case GI_TYPE_TAG_INT8:
124
+ return_value->v_int8 = (gint8) value;
125
+ case GI_TYPE_TAG_UINT8:
126
+ return_value->v_uint8 = (guint8) value;
128
+ case GI_TYPE_TAG_INT16:
129
+ return_value->v_int16 = (gint16) value;
131
+ case GI_TYPE_TAG_UINT16:
132
+ return_value->v_uint16 = (guint16) value;
134
+ case GI_TYPE_TAG_INT32:
135
+ return_value->v_int32 = (gint32) value;
137
+ case GI_TYPE_TAG_UINT32:
138
+ case GI_TYPE_TAG_BOOLEAN:
139
+ case GI_TYPE_TAG_UNICHAR:
140
+ return_value->v_uint32 = (guint32) value;
143
+ case GI_TYPE_TAG_INTERFACE:
145
+ GIBaseInfo* interface_info;
146
+ GIInfoType interface_type;
148
+ interface_info = g_type_info_get_interface(return_info);
149
+ interface_type = g_base_info_get_type(interface_info);
151
+ switch(interface_type) {
152
+ case GI_INFO_TYPE_ENUM:
153
+ case GI_INFO_TYPE_FLAGS:
154
+ return_value->v_int32 = (gint32) value;
157
+ return_value->v_pointer = (gpointer) value;
163
+ return_value->v_pointer = (gpointer) value;
170
gjs_invoke_c_function(JSContext *context,
172
@@ -329,7 +443,8 @@ gjs_invoke_c_function(JSContext *context,
173
GArgument *out_arg_cvalues;
174
GArgument *inout_original_arg_cvalues;
175
gpointer *ffi_arg_pointers;
176
- GArgument return_value;
177
+ ffi_arg return_value;
178
+ GArgument return_gargument;
180
guint8 processed_c_args = 0;
181
guint8 gi_argc, gi_arg_pos;
182
@@ -673,6 +788,8 @@ gjs_invoke_c_function(JSContext *context,
184
g_assert_cmpuint(next_rval, <, function->js_out_argc);
186
+ set_gargument_from_ffi_return_value(&return_info, &return_gargument, return_value);
188
array_length_pos = g_type_info_get_array_length(&return_info);
189
if (array_length_pos >= 0) {
190
GIArgInfo array_length_arg;
191
@@ -689,7 +806,7 @@ gjs_invoke_c_function(JSContext *context,
192
arg_failed = !gjs_value_from_explicit_array(context,
193
&return_values[next_rval],
197
JSVAL_TO_INT(length));
200
@@ -697,17 +814,17 @@ gjs_invoke_c_function(JSContext *context,
203
JSVAL_TO_INT(length),
205
+ &return_gargument))
208
arg_failed = !gjs_value_from_g_argument(context, &return_values[next_rval],
209
- &return_info, &return_value);
210
+ &return_info, &return_gargument);
211
/* Free GArgument, the jsval should have ref'd or copied it */
213
!gjs_g_argument_release(context,
217
+ &return_gargument))