1
From 889b4fc62f1b384f6956315c209ce7d8b97ea5e2 Mon Sep 17 00:00:00 2001
2
From: Colin Walters <walters@verbum.org>
3
Date: Wed, 4 Jan 2012 14:05:04 -0500
4
Subject: [PATCH 2/2] function: Fix ffi return value handling on 32 bit
6
We had two major problems in marshaling. One is that our conversion
7
routine took an unsigned ffi_arg value, which we put signed values
8
into. Also, our fallback case was copying from ffi_arg (which is
9
always 64 bit on architectures we support) into the pointer member of
10
the GIArgument union, but on 32 bit architecture pointers are just 32
13
Fix both of these by creating a new union, and then passing in a
14
pointer to the correct member of it for the given return value type
15
we're supplying to ffi. We then need to again convert from this union
16
type into a GIArgument.
18
Debugged with lots of help from Ray Strode <rstrode@redhat.com>
20
https://bugzilla.gnome.org/show_bug.cgi?id=665152
22
gi/function.c | 68 +++++++++++++++++++++++++++++++++++++++++++-------------
23
1 files changed, 52 insertions(+), 16 deletions(-)
25
diff --git a/gi/function.c b/gi/function.c
26
index dcba849..3755c20 100644
29
@@ -155,6 +155,7 @@ set_return_ffi_arg_from_giargument (GITypeInfo *ret_type,
30
switch (g_type_info_get_tag(ret_type)) {
31
case GI_TYPE_TAG_INT8:
32
*(ffi_sarg *) result = return_value->v_int8;
34
case GI_TYPE_TAG_UINT8:
35
*(ffi_arg *) result = return_value->v_uint8;
37
@@ -198,7 +199,7 @@ set_return_ffi_arg_from_giargument (GITypeInfo *ret_type,
41
- *(ffi_arg *) result = (ffi_arg) return_value->v_pointer;
42
+ *(ffi_arg *) result = (ffi_arg) return_value->v_uint64;
46
@@ -367,33 +368,57 @@ get_length_from_arg (GArgument *arg, GITypeTag tag)
48
/* Extract the correct bits from an ffi_arg return value into
49
* GIArgument: https://bugzilla.gnome.org/show_bug.cgi?id=665152
51
+ * Also see the ffi_call man page - the storage requirements for return
52
+ * values are "special".
54
+union GjsFFIReturnValue {
56
+ ffi_sarg rv_ffi_sarg;
63
-set_gargument_from_ffi_return_value (GITypeInfo *return_info,
64
- GIArgument *return_value,
66
+set_gargument_from_ffi_return_value (GITypeInfo *return_info,
67
+ GIArgument *return_value,
68
+ union GjsFFIReturnValue *value)
70
switch (g_type_info_get_tag (return_info)) {
71
case GI_TYPE_TAG_INT8:
72
- return_value->v_int8 = (gint8) value;
73
+ return_value->v_int8 = (gint8) value->rv_ffi_sarg;
75
case GI_TYPE_TAG_UINT8:
76
- return_value->v_uint8 = (guint8) value;
77
+ return_value->v_uint8 = (guint8) value->rv_ffi_arg;
79
case GI_TYPE_TAG_INT16:
80
- return_value->v_int16 = (gint16) value;
81
+ return_value->v_int16 = (gint16) value->rv_ffi_sarg;
83
case GI_TYPE_TAG_UINT16:
84
- return_value->v_uint16 = (guint16) value;
85
+ return_value->v_uint16 = (guint16) value->rv_ffi_arg;
87
case GI_TYPE_TAG_INT32:
88
- return_value->v_int32 = (gint32) value;
89
+ return_value->v_int32 = (gint32) value->rv_ffi_sarg;
91
case GI_TYPE_TAG_UINT32:
92
case GI_TYPE_TAG_BOOLEAN:
93
case GI_TYPE_TAG_UNICHAR:
94
- return_value->v_uint32 = (guint32) value;
95
+ return_value->v_uint32 = (guint32) value->rv_ffi_arg;
98
+ case GI_TYPE_TAG_INT64:
99
+ return_value->v_int64 = (gint64) value->rv_s64;
101
+ case GI_TYPE_TAG_UINT64:
102
+ return_value->v_uint64 = (guint64) value->rv_u64;
104
+ case GI_TYPE_TAG_FLOAT:
105
+ return_value->v_float = value->rv_float;
107
+ case GI_TYPE_TAG_DOUBLE:
108
+ return_value->v_double = value->rv_double;
110
case GI_TYPE_TAG_INTERFACE:
112
GIBaseInfo* interface_info;
113
@@ -405,16 +430,16 @@ set_gargument_from_ffi_return_value (GITypeInfo *return_info,
114
switch(interface_type) {
115
case GI_INFO_TYPE_ENUM:
116
case GI_INFO_TYPE_FLAGS:
117
- return_value->v_int32 = (gint32) value;
118
+ return_value->v_int32 = (gint32) value->rv_ffi_sarg;
121
- return_value->v_pointer = (gpointer) value;
122
+ return_value->v_pointer = (gpointer) value->rv_ffi_arg;
128
- return_value->v_pointer = (gpointer) value;
129
+ return_value->v_pointer = (gpointer) value->rv_ffi_arg;
133
@@ -443,7 +468,8 @@ gjs_invoke_c_function(JSContext *context,
134
GArgument *out_arg_cvalues;
135
GArgument *inout_original_arg_cvalues;
136
gpointer *ffi_arg_pointers;
137
- ffi_arg return_value;
138
+ union GjsFFIReturnValue return_value;
139
+ gpointer return_value_p; /* Will point inside the union return_value */
140
GArgument return_gargument;
142
guint8 processed_c_args = 0;
143
@@ -760,7 +786,17 @@ gjs_invoke_c_function(JSContext *context,
145
g_assert_cmpuint(c_arg_pos, ==, c_argc);
146
g_assert_cmpuint(gi_arg_pos, ==, gi_argc);
147
- ffi_call(&(function->invoker.cif), function->invoker.native_address, &return_value, ffi_arg_pointers);
149
+ /* See comment for GjsFFIReturnValue above */
150
+ if (return_tag == GI_TYPE_TAG_FLOAT)
151
+ return_value_p = &return_value.rv_float;
152
+ else if (return_tag == GI_TYPE_TAG_DOUBLE)
153
+ return_value_p = &return_value.rv_double;
154
+ else if (return_tag == GI_TYPE_TAG_INT64 || return_tag == GI_TYPE_TAG_UINT64)
155
+ return_value_p = &return_value.rv_u64;
157
+ return_value_p = &return_value.rv_ffi_arg;
158
+ ffi_call(&(function->invoker.cif), function->invoker.native_address, return_value_p, ffi_arg_pointers);
160
gjs_runtime_pop_context(JS_GetRuntime(context));
162
@@ -788,7 +824,7 @@ gjs_invoke_c_function(JSContext *context,
164
g_assert_cmpuint(next_rval, <, function->js_out_argc);
166
- set_gargument_from_ffi_return_value(&return_info, &return_gargument, return_value);
167
+ set_gargument_from_ffi_return_value(&return_info, &return_gargument, &return_value);
169
array_length_pos = g_type_info_get_array_length(&return_info);
170
if (array_length_pos >= 0) {