[vala/staging] codegen: Correctly handle signals returning real non-nullable struct
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/staging] codegen: Correctly handle signals returning real non-nullable struct
- Date: Sun, 12 Apr 2020 09:11:27 +0000 (UTC)
commit bcc40d5b971c3f5e3ebe928890b9aeba5ba32ba8
Author: Rico Tzschichholz <ricotz ubuntu com>
Date: Sun Apr 12 11:02:29 2020 +0200
codegen: Correctly handle signals returning real non-nullable struct
Fixes https://gitlab.gnome.org/GNOME/vala/issues/466
codegen/valagsignalmodule.vala | 89 +++++++++++++++++++++-----------
tests/Makefile.am | 1 +
tests/objects/signals-struct-return.vala | 46 +++++++++++++++++
3 files changed, 107 insertions(+), 29 deletions(-)
---
diff --git a/codegen/valagsignalmodule.vala b/codegen/valagsignalmodule.vala
index 909131775..108622815 100644
--- a/codegen/valagsignalmodule.vala
+++ b/codegen/valagsignalmodule.vala
@@ -24,8 +24,8 @@
public class Vala.GSignalModule : GObjectModule {
- string get_marshaller_function (List<Parameter> params, DataType return_type, string? prefix = null) {
- var signature = get_marshaller_signature (params, return_type);
+ string get_marshaller_function (Signal sig, List<Parameter> params, DataType return_type, string?
prefix = null) {
+ var signature = get_marshaller_signature (sig, params, return_type);
string ret;
if (prefix == null) {
@@ -38,12 +38,13 @@ public class Vala.GSignalModule : GObjectModule {
ret = "%s_%s_".printf (prefix, get_ccode_marshaller_type_name (return_type));
- if (params == null || params.size == 0) {
+ foreach (Parameter p in params) {
+ ret = "%s_%s".printf (ret, get_ccode_marshaller_type_name (p).replace (",", "_"));
+ }
+ if (sig.return_type.is_real_non_null_struct_type ()) {
+ ret = ret + "_POINTER";
+ } else if (params.size == 0) {
ret = ret + "_VOID";
- } else {
- foreach (Parameter p in params) {
- ret = "%s_%s".printf (ret, get_ccode_marshaller_type_name (p).replace (",",
"_"));
- }
}
return ret;
@@ -93,23 +94,24 @@ public class Vala.GSignalModule : GObjectModule {
}
}
- private string get_marshaller_signature (List<Parameter> params, DataType return_type) {
+ private string get_marshaller_signature (Signal sig, List<Parameter> params, DataType return_type) {
string signature;
signature = "%s:".printf (get_ccode_marshaller_type_name (return_type));
- if (params == null || params.size == 0) {
- signature = signature + "VOID";
- } else {
- bool first = true;
- foreach (Parameter p in params) {
- if (first) {
- signature = signature + get_ccode_marshaller_type_name (p);
- first = false;
- } else {
- signature = "%s,%s".printf (signature, get_ccode_marshaller_type_name
(p));
- }
+ bool first = true;
+ foreach (Parameter p in params) {
+ if (first) {
+ signature = signature + get_ccode_marshaller_type_name (p);
+ first = false;
+ } else {
+ signature = "%s,%s".printf (signature, get_ccode_marshaller_type_name (p));
}
}
+ if (sig.return_type.is_real_non_null_struct_type ()) {
+ signature = signature + (first ? "POINTER" : ",POINTER");
+ } else if (params.size == 0) {
+ signature = signature + "VOID";
+ }
return signature;
}
@@ -164,24 +166,29 @@ public class Vala.GSignalModule : GObjectModule {
sig.accept_children (this);
// declare parameter type
- foreach (Parameter p in sig.get_parameters ()) {
+ unowned List<Parameter> params = sig.get_parameters ();
+ foreach (Parameter p in params) {
generate_parameter (p, cfile, new HashMap<int,CCodeParameter> (), null);
}
- generate_marshaller (sig.get_parameters (), sig.return_type);
+ if (sig.return_type.is_real_non_null_struct_type ()) {
+ generate_marshaller (sig, params, new VoidType ());
+ } else {
+ generate_marshaller (sig, params, sig.return_type);
+ }
}
- void generate_marshaller (List<Parameter> params, DataType return_type) {
+ void generate_marshaller (Signal sig, List<Parameter> params, DataType return_type) {
string signature;
int n_params, i;
/* check whether a signal with the same signature already exists for this source file (or
predefined) */
- signature = get_marshaller_signature (params, return_type);
+ signature = get_marshaller_signature (sig, params, return_type);
if (predefined_marshal_set.contains (signature) || user_marshal_set.contains (signature)) {
return;
}
- var signal_marshaller = new CCodeFunction (get_marshaller_function (params, return_type,
null), "void");
+ var signal_marshaller = new CCodeFunction (get_marshaller_function (sig, params, return_type,
null), "void");
signal_marshaller.modifiers = CCodeModifiers.STATIC;
signal_marshaller.add_parameter (new CCodeParameter ("closure", "GClosure *"));
@@ -193,7 +200,7 @@ public class Vala.GSignalModule : GObjectModule {
push_function (signal_marshaller);
- var callback_decl = new CCodeFunctionDeclarator (get_marshaller_function (params,
return_type, "GMarshalFunc"));
+ var callback_decl = new CCodeFunctionDeclarator (get_marshaller_function (sig, params,
return_type, "GMarshalFunc"));
callback_decl.add_parameter (new CCodeParameter ("data1", "gpointer"));
n_params = 1;
foreach (Parameter p in params) {
@@ -218,10 +225,15 @@ public class Vala.GSignalModule : GObjectModule {
}
}
}
+ if (sig.return_type.is_real_non_null_struct_type ()) {
+ callback_decl.add_parameter (new CCodeParameter ("arg_%d".printf (n_params),
"gpointer"));
+ n_params++;
+ }
+
callback_decl.add_parameter (new CCodeParameter ("data2", "gpointer"));
ccode.add_statement (new CCodeTypeDefinition (get_value_type_name_from_type_reference
(return_type), callback_decl));
- ccode.add_declaration (get_marshaller_function (params, return_type, "GMarshalFunc"), new
CCodeVariableDeclarator ("callback"), CCodeModifiers.REGISTER);
+ ccode.add_declaration (get_marshaller_function (sig, params, return_type, "GMarshalFunc"),
new CCodeVariableDeclarator ("callback"), CCodeModifiers.REGISTER);
ccode.add_declaration ("GCClosure *", new CCodeVariableDeclarator ("cc", new
CCodeCastExpression (new CCodeIdentifier ("closure"), "GCClosure *")), CCodeModifiers.REGISTER);
@@ -254,7 +266,7 @@ public class Vala.GSignalModule : GObjectModule {
ccode.add_assignment (new CCodeIdentifier ("data2"), data);
ccode.close ();
- var c_assign_rhs = new CCodeCastExpression (new CCodeConditionalExpression (new
CCodeIdentifier ("marshal_data"), new CCodeIdentifier ("marshal_data"), new CCodeMemberAccess (new
CCodeIdentifier ("cc"), "callback", true)), get_marshaller_function (params, return_type, "GMarshalFunc"));
+ var c_assign_rhs = new CCodeCastExpression (new CCodeConditionalExpression (new
CCodeIdentifier ("marshal_data"), new CCodeIdentifier ("marshal_data"), new CCodeMemberAccess (new
CCodeIdentifier ("cc"), "callback", true)), get_marshaller_function (sig, params, return_type,
"GMarshalFunc"));
ccode.add_assignment (new CCodeIdentifier ("callback"), c_assign_rhs);
fc = new CCodeFunctionCall (new CCodeIdentifier ("callback"));
@@ -298,6 +310,12 @@ public class Vala.GSignalModule : GObjectModule {
}
}
}
+ if (sig.return_type.is_real_non_null_struct_type ()) {
+ var inner_fc = new CCodeFunctionCall (new CCodeIdentifier ("g_value_get_pointer"));
+ inner_fc.add_argument (new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, new
CCodeIdentifier ("param_values"), new CCodeIdentifier (i.to_string ())));
+ fc.add_argument (inner_fc);
+ i++;
+ }
fc.add_argument (new CCodeIdentifier ("data2"));
if (return_type.type_symbol != null || return_type is ArrayType) {
@@ -379,12 +397,17 @@ public class Vala.GSignalModule : GObjectModule {
csignew.add_argument (new CCodeConstant ("NULL"));
csignew.add_argument (new CCodeConstant ("NULL"));
- string marshaller = get_marshaller_function (sig.get_parameters (), sig.return_type);
+ unowned List<Parameter> params = sig.get_parameters ();
+ string marshaller;
+ if (sig.return_type.is_real_non_null_struct_type ()) {
+ marshaller = get_marshaller_function (sig, params, new VoidType ());
+ } else {
+ marshaller = get_marshaller_function (sig, params, sig.return_type);
+ }
var marshal_arg = new CCodeIdentifier (marshaller);
csignew.add_argument (marshal_arg);
- var params = sig.get_parameters ();
if (sig.return_type is PointerType || sig.return_type is GenericType) {
csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER"));
} else if (sig.return_type is ErrorType) {
@@ -393,6 +416,8 @@ public class Vala.GSignalModule : GObjectModule {
csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER"));
} else if (sig.return_type.type_symbol == null) {
csignew.add_argument (new CCodeConstant ("G_TYPE_NONE"));
+ } else if (sig.return_type.is_real_non_null_struct_type ()) {
+ csignew.add_argument (new CCodeConstant ("G_TYPE_NONE"));
} else {
csignew.add_argument (new CCodeConstant (get_ccode_type_id
(sig.return_type.type_symbol)));
}
@@ -412,6 +437,9 @@ public class Vala.GSignalModule : GObjectModule {
}
}
}
+ if (sig.return_type.is_real_non_null_struct_type ()) {
+ params_len++;
+ }
csignew.add_argument (new CCodeConstant ("%d".printf (params_len)));
foreach (Parameter param in params) {
@@ -446,6 +474,9 @@ public class Vala.GSignalModule : GObjectModule {
csignew.add_argument (new CCodeConstant (get_ccode_type_id
(param.variable_type.type_symbol)));
}
}
+ if (sig.return_type.is_real_non_null_struct_type ()) {
+ csignew.add_argument (new CCodeConstant ("G_TYPE_POINTER"));
+ }
marshal_arg.name = marshaller;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index af7a89f37..8f942e8e3 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -417,6 +417,7 @@ TESTS = \
objects/signals-fundamental-return.vala \
objects/signals-gobject-return.vala \
objects/signals-lambda-delegate.vala \
+ objects/signals-struct-return.vala \
objects/singleton.vala \
objects/test-025.vala \
objects/test-026.vala \
diff --git a/tests/objects/signals-struct-return.vala b/tests/objects/signals-struct-return.vala
new file mode 100644
index 000000000..4790d9d9d
--- /dev/null
+++ b/tests/objects/signals-struct-return.vala
@@ -0,0 +1,46 @@
+struct Foo {
+ public string s;
+ public int i;
+}
+
+class Bar : Object {
+ public signal Foo on_foo ();
+ public signal Foo on_foo_with_arg (string s);
+ public signal Foo? on_bar ();
+ public signal Foo? on_bar_with_arg (string s);
+}
+
+void main () {
+ {
+ var bar = new Bar ();
+ bar.on_foo.connect (() => {
+ return { "foo", 23 };
+ });
+ bar.on_foo_with_arg.connect ((s) => {
+ assert (s == "foo");
+ return { "foo", 42 };
+ });
+ var foo = bar.on_foo ();
+ assert (foo.s == "foo");
+ assert (foo.i == 23);
+ var foo2 = bar.on_foo_with_arg ("foo");
+ assert (foo2.s == "foo");
+ assert (foo2.i == 42);
+ }
+ {
+ var bar = new Bar ();
+ bar.on_bar.connect (() => {
+ return { "bar", 42 };
+ });
+ bar.on_bar_with_arg.connect ((s) => {
+ assert (s == "bar");
+ return { "bar", 23 };
+ });
+ var foo = bar.on_bar ();
+ assert (foo.s == "bar");
+ assert (foo.i == 42);
+ var foo2 = bar.on_bar_with_arg ("bar");
+ assert (foo2.s == "bar");
+ assert (foo2.i == 23);
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]