[gjs/wip/gobj-kitchen-sink: 3/21] function: Allow out parameters in callbacks and vfuncs
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/wip/gobj-kitchen-sink: 3/21] function: Allow out parameters in callbacks and vfuncs
- Date: Fri, 27 Jan 2012 20:06:44 +0000 (UTC)
commit 6fd48fc376e6a6b19b1c7d7268ecbff9688e64cd
Author: Jasper St. Pierre <jstpierre mecheye net>
Date: Mon Nov 28 07:40:28 2011 -0500
function: Allow out parameters in callbacks and vfuncs
If a callback needs an out parameter or return value to work,
we need a way for vfunc implementation to take advantage of this.
The pattern:
If the callback takes a non-void return value and no out args:
The callback should return the return value:
return return_value;
If the callback takes no return value and has one out arg:
The callback should return the one out arg:
return out_arg_1;
If the callback takes no return value and has multiple out args:
The callback should return an array containg the out args in sequence:
return [out_arg_1, out_arg_2, ..., out_arg_N];
If the callback takes a non-void return value and has multiple out args:
The callback should return an array containing first the return value,
then the out args in sequence:
return [return_value, out_arg_1, out_arg_2, ..., out_arg_N];
https://bugzilla.gnome.org/show_bug.cgi?id=663492
gi/function.c | 119 +++++++++++++++++++++++++++++++++++++-----
test/js/testGIMarshalling.js | 48 +++++++++++++++++
2 files changed, 153 insertions(+), 14 deletions(-)
---
diff --git a/gi/function.c b/gi/function.c
index 1fe354d..4ce4780 100644
--- a/gi/function.c
+++ b/gi/function.c
@@ -208,11 +208,11 @@ gjs_callback_closure(ffi_cif *cif,
{
JSContext *context;
GjsCallbackTrampoline *trampoline;
- int i, n_args, n_jsargs;
+ int i, n_args, n_jsargs, n_outargs;
jsval *jsargs, rval;
GITypeInfo ret_type;
- GArgument return_value;
gboolean success = FALSE;
+ gboolean ret_type_is_void;
trampoline = data;
g_assert(trampoline);
@@ -224,6 +224,7 @@ gjs_callback_closure(ffi_cif *cif,
g_assert(n_args >= 0);
+ n_outargs = 0;
jsargs = (jsval*)g_newa(jsval, n_args);
for (i = 0, n_jsargs = 0; i < n_args; i++) {
GIArgInfo arg_info;
@@ -236,6 +237,14 @@ gjs_callback_closure(ffi_cif *cif,
if (g_type_info_get_tag(&type_info) == GI_TYPE_TAG_VOID)
continue;
+ if (g_arg_info_get_direction(&arg_info) == GI_DIRECTION_OUT) {
+ n_outargs++;
+ continue;
+ }
+
+ if (g_arg_info_get_direction(&arg_info) == GI_DIRECTION_INOUT)
+ n_outargs++;
+
if (!gjs_value_from_g_argument(context,
&jsargs[n_jsargs++],
&type_info,
@@ -253,20 +262,102 @@ gjs_callback_closure(ffi_cif *cif,
}
g_callable_info_load_return_type(trampoline->info, &ret_type);
+ ret_type_is_void = g_type_info_get_tag (&ret_type) == GI_TYPE_TAG_VOID;
+
+ if (n_outargs == 0 && !ret_type_is_void) {
+ GIArgument argument;
+
+ /* non-void return value, no out args. Should
+ * be a single return value. */
+ if (!gjs_value_to_g_argument(context,
+ rval,
+ &ret_type,
+ "callback",
+ GJS_ARGUMENT_RETURN_VALUE,
+ GI_TRANSFER_NOTHING,
+ TRUE,
+ &argument))
+ goto out;
- if (!gjs_value_to_g_argument(context,
- rval,
- &ret_type,
- "callback",
- GJS_ARGUMENT_RETURN_VALUE,
- FALSE,
- TRUE,
- &return_value)) {
- goto out;
- }
+ set_return_ffi_arg_from_giargument(&ret_type,
+ result,
+ &argument);
+ } else if (n_outargs == 1 && ret_type_is_void) {
+ /* void return value, one out args. Should
+ * be a single return value. */
+ for (i = 0; i < n_args; i++) {
+ GIArgInfo arg_info;
+ GITypeInfo type_info;
+ g_callable_info_load_arg(trampoline->info, i, &arg_info);
+ if (g_arg_info_get_direction(&arg_info) == GI_DIRECTION_IN)
+ continue;
+
+ g_arg_info_load_type(&arg_info, &type_info);
+ if (!gjs_value_to_g_argument(context,
+ rval,
+ &type_info,
+ "callback",
+ GJS_ARGUMENT_ARGUMENT,
+ GI_TRANSFER_NOTHING,
+ TRUE,
+ *(gpointer *)args[i]))
+ goto out;
-
- set_return_ffi_arg_from_giargument(&ret_type, result, &return_value);
+ break;
+ }
+ } else {
+ jsval elem;
+ gsize elem_idx = 0;
+ /* more than one of a return value or an out argument.
+ * Should be an array of output values. */
+
+ if (!ret_type_is_void) {
+ GIArgument argument;
+
+ if (!JS_GetElement(context, JSVAL_TO_OBJECT(rval), elem_idx, &elem))
+ goto out;
+
+ if (!gjs_value_to_g_argument(context,
+ elem,
+ &ret_type,
+ "callback",
+ GJS_ARGUMENT_ARGUMENT,
+ GI_TRANSFER_NOTHING,
+ TRUE,
+ &argument))
+ goto out;
+
+ set_return_ffi_arg_from_giargument(&ret_type,
+ result,
+ &argument);
+
+ elem_idx++;
+ }
+
+ for (i = 0; i < n_args; i++) {
+ GIArgInfo arg_info;
+ GITypeInfo type_info;
+ g_callable_info_load_arg(trampoline->info, i, &arg_info);
+ if (g_arg_info_get_direction(&arg_info) == GI_DIRECTION_IN)
+ continue;
+
+ g_arg_info_load_type(&arg_info, &type_info);
+ if (!JS_GetElement(context, JSVAL_TO_OBJECT(rval), elem_idx, &elem))
+ goto out;
+
+ if (!gjs_value_to_g_argument(context,
+ elem,
+ &type_info,
+ "callback",
+ GJS_ARGUMENT_ARGUMENT,
+ GI_TRANSFER_NOTHING,
+ TRUE,
+ *(gpointer *)args[i]))
+ goto out;
+
+ elem_idx++;
+ }
+ }
success = TRUE;
diff --git a/test/js/testGIMarshalling.js b/test/js/testGIMarshalling.js
index 57dcbfc..252c96b 100644
--- a/test/js/testGIMarshalling.js
+++ b/test/js/testGIMarshalling.js
@@ -230,4 +230,52 @@ function testGType() {
assertEquals(GObject.TYPE_INT, GIMarshallingTests.gtype_inout(GObject.TYPE_NONE));
}
+const VFuncTester = new Lang.Class({
+ Name: 'VFuncTester',
+ Extends: GIMarshallingTests.Object,
+
+ do_vfunc_return_value_only: function(obj) {
+ return 42;
+ },
+
+ do_vfunc_one_out_parameter: function(obj) {
+ return 43;
+ },
+
+ do_vfunc_multiple_out_parameters: function(obj) {
+ return [44, 45];
+ },
+
+ do_vfunc_return_value_and_one_out_parameter: function(obj) {
+ return [46, 47];
+ },
+
+ do_vfunc_return_value_and_multiple_out_parameters: function(obj) {
+ return [48, 49, 50];
+ }
+});
+
+function testVFuncs() {
+ let tester = new VFuncTester();
+ let a, b, c;
+ a = tester.vfunc_return_value_only();
+ assertEquals(42, a);
+
+ a = tester.vfunc_one_out_parameter();
+ assertEquals(43, a);
+
+ [a, b] = tester.vfunc_multiple_out_parameters();
+ assertEquals(44, a);
+ assertEquals(45, b);
+
+ [a, b] = tester.vfunc_return_value_and_one_out_parameter();
+ assertEquals(46, a);
+ assertEquals(47, b);
+
+ [a, b, c] = tester.vfunc_return_value_and_multiple_out_parameters();
+ assertEquals(48, a);
+ assertEquals(49, b);
+ assertEquals(50, c);
+}
+
gjstestRun();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]