[vala/wip/transform: 305/373] GDBus client transformer
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/wip/transform: 305/373] GDBus client transformer
- Date: Mon, 22 Oct 2018 14:57:44 +0000 (UTC)
commit 81b2662428b23b810cda0e7b7fd1c35bfa0be965
Author: Luca Bruno <lucabru src gnome org>
Date: Tue Jan 3 17:22:35 2012 +0100
GDBus client transformer
codegen/Makefile.am | 1 +
codegen/valagdbusclientmodule.vala | 942 +-------------------------------
codegen/valagdbusclienttransformer.vala | 347 ++++++++++++
codegen/valagvariantmodule.vala | 8 -
codegen/valagvarianttransformer.vala | 4 +-
compiler/valacompiler.vala | 2 +-
vala/valacodebuilder.vala | 2 +-
vala/valacodetransformer.vala | 16 +-
vapi/gio-2.0.vapi | 2 +-
vapi/metadata/Gio-2.0.metadata | 1 +
10 files changed, 366 insertions(+), 959 deletions(-)
---
diff --git a/codegen/Makefile.am b/codegen/Makefile.am
index b57dc1e62..49421eb45 100644
--- a/codegen/Makefile.am
+++ b/codegen/Makefile.am
@@ -40,6 +40,7 @@ libvalaccodegen_la_VALASOURCES = \
valaenumregisterfunction.vala \
valagasyncmodule.vala \
valagdbusclientmodule.vala \
+ valagdbusclienttransformer.vala \
valagdbusmodule.vala \
valagdbusservermodule.vala \
valagerrormodule.vala \
diff --git a/codegen/valagdbusclientmodule.vala b/codegen/valagdbusclientmodule.vala
index 91bdce363..6f917245c 100644
--- a/codegen/valagdbusclientmodule.vala
+++ b/codegen/valagdbusclientmodule.vala
@@ -22,24 +22,8 @@
*/
public class Vala.GDBusClientModule : GDBusModule {
- enum CallType {
- SYNC,
- ASYNC,
- FINISH,
- NO_REPLY
- }
-
- public CCodeConstant get_dbus_timeout (Symbol symbol) {
- int timeout = -1;
-
- var dbus = symbol.get_attribute ("DBus");
- if (dbus != null && dbus.has_argument ("timeout")) {
- timeout = dbus.get_integer ("timeout");
- } else if (symbol.parent_symbol != null) {
- return get_dbus_timeout (symbol.parent_symbol);
- }
-
- return new CCodeConstant (timeout.to_string ());
+ CCodeExpression get_interface_info (ObjectTypeSymbol sym) {
+ return new CCodeIdentifier ("_" + get_ccode_lower_case_prefix (sym) + "dbus_interface_info");
}
public override void generate_dynamic_method_wrapper (DynamicMethod method) {
@@ -55,7 +39,7 @@ public class Vala.GDBusClientModule : GDBusModule {
push_function (func);
if (dynamic_method.dynamic_type.data_type == dbus_proxy_type) {
- generate_marshalling (method, CallType.SYNC, null, method.name, -1);
+ //generate_marshalling (method, CallType.SYNC, null, method.name, -1);
} else {
Report.error (method.source_reference, "dynamic methods are not supported for
`%s'".printf (dynamic_method.dynamic_type.to_string ()));
}
@@ -66,183 +50,6 @@ public class Vala.GDBusClientModule : GDBusModule {
cfile.add_function (func);
}
- void generate_proxy_interface_init (Interface main_iface, Interface iface) {
- // also generate proxy for prerequisites
- foreach (var prereq in iface.get_prerequisites ()) {
- if (prereq.data_type is Interface) {
- generate_proxy_interface_init (main_iface, (Interface) prereq.data_type);
- }
- }
-
- string lower_cname = get_ccode_lower_case_prefix (main_iface) + "proxy";
-
- var proxy_iface_init = new CCodeFunction (lower_cname + "_" + get_ccode_lower_case_prefix
(iface) + "interface_init", "void");
- proxy_iface_init.add_parameter (new CCodeParameter ("iface", get_ccode_name (iface) +
"Iface*"));
-
- push_function (proxy_iface_init);
-
- foreach (Method m in iface.get_methods ()) {
- if (!m.is_abstract) {
- continue;
- }
-
- var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"),
get_ccode_vfunc_name (m));
- if (!m.coroutine) {
- ccode.add_assignment (vfunc_entry, new CCodeIdentifier
(generate_dbus_proxy_method (main_iface, iface, m)));
- } else {
- ccode.add_assignment (vfunc_entry, new CCodeIdentifier
(generate_async_dbus_proxy_method (main_iface, iface, m)));
- vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier ("iface"),
get_ccode_finish_vfunc_name (m));
- ccode.add_assignment (vfunc_entry, new CCodeIdentifier
(generate_finish_dbus_proxy_method (main_iface, iface, m)));
- }
- }
-
- foreach (Property prop in iface.get_properties ()) {
- if (!prop.is_abstract) {
- continue;
- }
-
- if (prop.get_accessor != null) {
- var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier
("iface"), "get_" + prop.name);
- ccode.add_assignment (vfunc_entry, new CCodeIdentifier
(generate_dbus_proxy_property_get (main_iface, iface, prop)));
- }
- if (prop.set_accessor != null) {
- var vfunc_entry = new CCodeMemberAccess.pointer (new CCodeIdentifier
("iface"), "set_" + prop.name);
- ccode.add_assignment (vfunc_entry, new CCodeIdentifier
(generate_dbus_proxy_property_set (main_iface, iface, prop)));
- }
- }
-
- proxy_iface_init.modifiers = CCodeModifiers.STATIC;
- pop_function ();
- cfile.add_function_declaration (proxy_iface_init);
- cfile.add_function (proxy_iface_init);
- }
-
- string implement_interface (CCodeFunctionCall define_type, Interface main_iface, Interface iface) {
- string result = "";
-
- // also implement prerequisites
- foreach (var prereq in iface.get_prerequisites ()) {
- if (prereq.data_type is Interface) {
- result += implement_interface (define_type, main_iface, (Interface)
prereq.data_type);
- }
- }
-
- string interface_macro;
-
- if (in_plugin) {
- interface_macro = "G_IMPLEMENT_INTERFACE_DYNAMIC";
- } else {
- interface_macro = "G_IMPLEMENT_INTERFACE";
- }
-
- result += "%s (%s, %sproxy_%sinterface_init) ".printf (
- interface_macro,
- get_ccode_upper_case_name (iface, "TYPE_"),
- get_ccode_lower_case_prefix (main_iface),
- get_ccode_lower_case_prefix (iface));
- return result;
- }
-
- public override void generate_interface_declaration (Interface iface, CCodeFile decl_space) {
- base.generate_interface_declaration (iface, decl_space);
-
- string dbus_iface_name = get_dbus_name (iface);
- if (dbus_iface_name == null) {
- return;
- }
-
- string get_type_name = "%sproxy_get_type".printf (get_ccode_lower_case_prefix (iface));
-
- if (add_symbol_declaration (decl_space, iface, get_type_name)) {
- return;
- }
-
- decl_space.add_type_declaration (new CCodeNewline ());
- var macro = "(%s ())".printf (get_type_name);
- decl_space.add_type_declaration (new CCodeMacroReplacement ("%s_PROXY".printf
(get_ccode_type_id (iface)), macro));
-
- // declare proxy_get_type function
- var proxy_get_type = new CCodeFunction (get_type_name, "GType");
- proxy_get_type.modifiers = CCodeModifiers.CONST;
- decl_space.add_function_declaration (proxy_get_type);
-
- if (in_plugin) {
- var proxy_register_type = new CCodeFunction ("%sproxy_register_dynamic_type".printf
(get_ccode_lower_case_prefix (iface)));
- proxy_register_type.add_parameter (new CCodeParameter ("module", "GTypeModule*"));
- decl_space.add_function_declaration (proxy_register_type);
- }
- }
-
- public override void visit_interface (Interface iface) {
- base.visit_interface (iface);
-
- string dbus_iface_name = get_dbus_name (iface);
- if (dbus_iface_name == null) {
- return;
- }
-
- cfile.add_include ("gio/gio.h");
-
- // create proxy class
- string cname = get_ccode_name (iface) + "Proxy";
- string lower_cname = get_ccode_lower_case_prefix (iface) + "proxy";
-
- cfile.add_type_declaration (new CCodeTypeDefinition ("GDBusProxy", new
CCodeVariableDeclarator (cname)));
- cfile.add_type_declaration (new CCodeTypeDefinition ("GDBusProxyClass", new
CCodeVariableDeclarator (cname + "Class")));
-
- string type_macro;
-
- if (in_plugin) {
- type_macro = "G_DEFINE_DYNAMIC_TYPE_EXTENDED";
- } else {
- type_macro = "G_DEFINE_TYPE_EXTENDED";
- }
-
- var define_type = new CCodeFunctionCall (new CCodeIdentifier (type_macro));
- define_type.add_argument (new CCodeIdentifier (cname));
- define_type.add_argument (new CCodeIdentifier (lower_cname));
- define_type.add_argument (new CCodeIdentifier ("G_TYPE_DBUS_PROXY"));
- define_type.add_argument (new CCodeConstant ("0"));
- define_type.add_argument (new CCodeIdentifier (implement_interface (define_type, iface,
iface)));
-
- cfile.add_type_member_definition (define_type);
-
- var proxy_class_init = new CCodeFunction (lower_cname + "_class_init", "void");
- proxy_class_init.add_parameter (new CCodeParameter ("klass", cname + "Class*"));
- proxy_class_init.modifiers = CCodeModifiers.STATIC;
- push_function (proxy_class_init);
- var proxy_class = new CCodeFunctionCall (new CCodeIdentifier ("G_DBUS_PROXY_CLASS"));
- proxy_class.add_argument (new CCodeIdentifier ("klass"));
- ccode.add_assignment (new CCodeMemberAccess.pointer (proxy_class, "g_signal"), new
CCodeIdentifier (lower_cname + "_g_signal"));
- pop_function ();
- cfile.add_function (proxy_class_init);
-
- generate_signal_handler_function (iface);
-
- if (in_plugin) {
- var proxy_class_finalize = new CCodeFunction (lower_cname + "_class_finalize",
"void");
- proxy_class_finalize.add_parameter (new CCodeParameter ("klass", cname + "Class*"));
- proxy_class_finalize.modifiers = CCodeModifiers.STATIC;
- cfile.add_function (proxy_class_finalize);
-
- var proxy_type_init = new CCodeFunction (lower_cname + "_register_dynamic_type",
"void");
- proxy_type_init.add_parameter (new CCodeParameter ("module", "GTypeModule*"));
- push_function (proxy_type_init);
- var call_register_type = new CCodeFunctionCall (new CCodeIdentifier (lower_cname +
"_register_type"));
- call_register_type.add_argument (new CCodeIdentifier ("module"));
- ccode.add_expression (call_register_type);
- pop_function ();
- cfile.add_function(proxy_type_init);
- }
-
- var proxy_instance_init = new CCodeFunction (lower_cname + "_init", "void");
- proxy_instance_init.add_parameter (new CCodeParameter ("self", cname + "*"));
- proxy_instance_init.modifiers = CCodeModifiers.STATIC;
- cfile.add_function (proxy_instance_init);
-
- generate_proxy_interface_init (iface, iface);
- }
-
public override void visit_method_call (MethodCall expr) {
var mtype = expr.call.value_type as MethodType;
bool bus_get_proxy_async = (mtype != null && get_ccode_name (mtype.method_symbol) ==
"g_bus_get_proxy");
@@ -435,749 +242,6 @@ public class Vala.GDBusClientModule : GDBusModule {
set_cvalue (expr, temp_ref);
}
- string generate_dbus_signal_handler (Signal sig, ObjectTypeSymbol sym) {
- string wrapper_name = "_dbus_handle_%s_%s".printf (get_ccode_lower_case_name (sym),
get_ccode_lower_case_name (sig));
-
- var function = new CCodeFunction (wrapper_name);
- function.modifiers = CCodeModifiers.STATIC;
- function.add_parameter (new CCodeParameter ("self", get_ccode_name (sym) + "*"));
- function.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
-
- push_function (function);
-
- ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator ("_arguments_iter"));
-
- var iter_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_iter_init"));
- iter_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new
CCodeIdentifier ("_arguments_iter")));
- iter_init.add_argument (new CCodeIdentifier ("parameters"));
- ccode.add_expression (iter_init);
-
- var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name"));
- ccall.add_argument (new CCodeIdentifier ("self"));
- ccall.add_argument (get_signal_canonical_constant (sig));
-
- foreach (Parameter param in sig.get_parameters ()) {
- var param_name = get_variable_cname (param.name);
- var owned_type = param.variable_type.copy ();
- owned_type.value_owned = true;
-
- ccode.add_declaration (get_ccode_name (owned_type), new CCodeVariableDeclarator.zero
(param_name, default_value_for_type (param.variable_type, true)));
-
- var st = param.variable_type.data_type as Struct;
- if (st != null && !st.is_simple_type ()) {
- ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF,
new CCodeIdentifier (param_name)));
- } else {
- ccall.add_argument (new CCodeIdentifier (param_name));
- }
-
- if (param.variable_type is ArrayType) {
- var array_type = (ArrayType) param.variable_type;
-
- for (int dim = 1; dim <= array_type.rank; dim++) {
- string length_cname = get_parameter_array_length_cname (param, dim);
-
- ccode.add_declaration ("int", new CCodeVariableDeclarator
(length_cname, new CCodeConstant ("0")));
- ccall.add_argument (new CCodeIdentifier (length_cname));
- }
- }
-
- read_expression (param.variable_type, new CCodeIdentifier ("_arguments_iter"), new
CCodeIdentifier (param_name), param);
- }
-
- ccode.add_expression (ccall);
-
- foreach (Parameter param in sig.get_parameters ()) {
- var owned_type = param.variable_type.copy ();
- owned_type.value_owned = true;
-
- if (requires_destroy (owned_type)) {
- // keep local alive (symbol_reference is weak)
- var local = new LocalVariable (owned_type, param.name);
- ccode.add_expression (destroy_local (local));
- }
- }
-
- pop_function ();
-
- cfile.add_function_declaration (function);
- cfile.add_function (function);
-
- return wrapper_name;
- }
-
- void generate_signal_handler_function (ObjectTypeSymbol sym) {
- var cfunc = new CCodeFunction (get_ccode_lower_case_prefix (sym) + "proxy_g_signal", "void");
- cfunc.add_parameter (new CCodeParameter ("proxy", "GDBusProxy*"));
- cfunc.add_parameter (new CCodeParameter ("sender_name", "const gchar*"));
- cfunc.add_parameter (new CCodeParameter ("signal_name", "const gchar*"));
- cfunc.add_parameter (new CCodeParameter ("parameters", "GVariant*"));
-
- cfunc.modifiers |= CCodeModifiers.STATIC;
-
- cfile.add_function_declaration (cfunc);
-
- push_function (cfunc);
-
- bool firstif = true;
-
- foreach (Signal sig in sym.get_signals ()) {
- if (sig.access != SymbolAccessibility.PUBLIC) {
- continue;
- }
-
- cfile.add_include ("string.h");
-
- var ccheck = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
- ccheck.add_argument (new CCodeIdentifier ("signal_name"));
- ccheck.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member
(sig))));
-
- var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ccheck, new
CCodeConstant ("0"));
- if (firstif) {
- ccode.open_if (cond);
- firstif = false;
- } else {
- ccode.else_if (cond);
- }
-
- var ccall = new CCodeFunctionCall (new CCodeIdentifier (generate_dbus_signal_handler
(sig, sym)));
- ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("proxy"),
get_ccode_name (sym) + "*"));
- ccall.add_argument (new CCodeIdentifier ("parameters"));
-
- ccode.add_expression (ccall);
- }
- if (!firstif) {
- ccode.close ();
- }
-
- pop_function ();
-
- cfile.add_function (cfunc);
- }
-
- void generate_marshalling (Method m, CallType call_type, string? iface_name, string? method_name, int
method_timeout) {
- var gdbusproxy = new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *");
-
- var connection = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_connection"));
- connection.add_argument (gdbusproxy);
-
- bool uses_fd = dbus_method_uses_file_descriptor (m);
- if (uses_fd) {
- cfile.add_include ("gio/gunixfdlist.h");
- ccode.add_declaration ("GUnixFDList*", new CCodeVariableDeclarator ("_fd_list"));
- }
-
- bool has_error_argument = m.tree_can_fail;
- CCodeExpression error_argument;
- if (has_error_argument) {
- error_argument = new CCodeIdentifier ("error");
- } else {
- error_argument = new CCodeConstant ("NULL");
- }
-
- if (call_type != CallType.FINISH) {
- var destination = new CCodeFunctionCall (new CCodeIdentifier
("g_dbus_proxy_get_name"));
- destination.add_argument (gdbusproxy);
-
- var interface_name = new CCodeFunctionCall (new CCodeIdentifier
("g_dbus_proxy_get_interface_name"));
- interface_name.add_argument (gdbusproxy);
-
- var object_path = new CCodeFunctionCall (new CCodeIdentifier
("g_dbus_proxy_get_object_path"));
- object_path.add_argument (gdbusproxy);
-
- CCodeExpression timeout;
- if (method_timeout <= 0) {
- timeout = new CCodeFunctionCall (new CCodeIdentifier
("g_dbus_proxy_get_default_timeout"));
- ((CCodeFunctionCall) timeout).add_argument (gdbusproxy);
- } else {
- timeout = new CCodeConstant ("%d".printf (method_timeout));
- }
-
- // register errors
- var error_types = new ArrayList<DataType> ();
- m.get_error_types (error_types);
- foreach (var error_type in error_types) {
- var errtype = (ErrorType) error_type;
- if (errtype.error_domain != null) {
- ccode.add_expression (new CCodeIdentifier (get_ccode_upper_case_name
(errtype.error_domain)));
- }
- }
-
- // build D-Bus message
-
- ccode.add_declaration ("GDBusMessage", new CCodeVariableDeclarator ("*_message"));
-
- var ccall = new CCodeFunctionCall (new CCodeIdentifier
("g_dbus_message_new_method_call"));
- ccall.add_argument (destination);
- ccall.add_argument (object_path);
- if (iface_name != null) {
- ccall.add_argument (new CCodeConstant ("\"%s\"".printf (iface_name)));
- } else {
- ccall.add_argument (interface_name);
- }
- ccall.add_argument (new CCodeConstant ("\"%s\"".printf (method_name)));
- ccode.add_assignment (new CCodeIdentifier ("_message"), ccall);
-
- ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
- ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator
("_arguments_builder"));
-
- var builder_init = new CCodeFunctionCall (new CCodeIdentifier
("g_variant_builder_init"));
- builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF,
new CCodeIdentifier ("_arguments_builder")));
- builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
- ccode.add_expression (builder_init);
-
- if (uses_fd) {
- ccode.add_assignment (new CCodeIdentifier ("_fd_list"), new CCodeFunctionCall
(new CCodeIdentifier ("g_unix_fd_list_new")));
- }
-
- CCodeExpression cancellable = new CCodeConstant ("NULL");
-
- foreach (Parameter param in m.get_parameters ()) {
- if (param.direction == ParameterDirection.IN) {
- CCodeExpression expr = new CCodeIdentifier (get_variable_cname
(param.name));
- if (param.variable_type.is_real_struct_type ()) {
- expr = new CCodeUnaryExpression
(CCodeUnaryOperator.POINTER_INDIRECTION, expr);
- }
-
- if (param.variable_type is ObjectType &&
param.variable_type.data_type.get_full_name () == "GLib.Cancellable") {
- cancellable = expr;
- continue;
- }
-
- if (param.variable_type is ObjectType &&
param.variable_type.data_type.get_full_name () == "GLib.BusName") {
- // ignore BusName sender parameters
- continue;
- }
-
- send_dbus_value (param.variable_type, new CCodeIdentifier
("_arguments_builder"), expr, param);
- }
- }
-
- var builder_end = new CCodeFunctionCall (new CCodeIdentifier
("g_variant_builder_end"));
- builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF,
new CCodeIdentifier ("_arguments_builder")));
- ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
-
- var set_body = new CCodeFunctionCall (new CCodeIdentifier
("g_dbus_message_set_body"));
- set_body.add_argument (new CCodeIdentifier ("_message"));
- set_body.add_argument (new CCodeIdentifier ("_arguments"));
- ccode.add_expression (set_body);
-
- if (uses_fd) {
- ccall = new CCodeFunctionCall (new CCodeIdentifier
("g_dbus_message_set_unix_fd_list"));
- ccall.add_argument (new CCodeIdentifier ("_message"));
- ccall.add_argument (new CCodeIdentifier ("_fd_list"));
- ccode.add_expression (ccall);
-
- ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
- ccall.add_argument (new CCodeIdentifier ("_fd_list"));
- ccode.add_expression (ccall);
- }
-
- // send D-Bus message
-
- if (call_type == CallType.SYNC) {
- ccall = new CCodeFunctionCall (new CCodeIdentifier
("g_dbus_connection_send_message_with_reply_sync"));
- ccall.add_argument (connection);
- ccall.add_argument (new CCodeIdentifier ("_message"));
- ccall.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
- ccall.add_argument (timeout);
- ccall.add_argument (new CCodeConstant ("NULL"));
- ccall.add_argument (cancellable);
- ccall.add_argument (error_argument);
- ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall);
- } else if (call_type == CallType.NO_REPLY) {
- var set_flags = new CCodeFunctionCall (new CCodeIdentifier
("g_dbus_message_set_flags"));
- set_flags.add_argument (new CCodeIdentifier ("_message"));
- set_flags.add_argument (new CCodeConstant
("G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED"));
- ccode.add_expression (set_flags);
-
- ccall = new CCodeFunctionCall (new CCodeIdentifier
("g_dbus_connection_send_message"));
- ccall.add_argument (connection);
- ccall.add_argument (new CCodeIdentifier ("_message"));
- ccall.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
- ccall.add_argument (new CCodeConstant ("NULL"));
- ccall.add_argument (error_argument);
- ccode.add_expression (ccall);
- } else if (call_type == CallType.ASYNC) {
- ccall = new CCodeFunctionCall (new CCodeIdentifier
("g_dbus_connection_send_message_with_reply"));
- ccall.add_argument (connection);
- ccall.add_argument (new CCodeIdentifier ("_message"));
- ccall.add_argument (new CCodeConstant ("G_DBUS_SEND_MESSAGE_FLAGS_NONE"));
- ccall.add_argument (timeout);
- ccall.add_argument (new CCodeConstant ("NULL"));
- ccall.add_argument (cancellable);
-
- CCodeFunctionCall res_wrapper = null;
-
- // use wrapper as source_object wouldn't be correct otherwise
- ccall.add_argument (new CCodeIdentifier (generate_async_callback_wrapper ()));
- res_wrapper = new CCodeFunctionCall (new CCodeIdentifier ("g_task_new"));
- res_wrapper.add_argument (new CCodeCastExpression (new CCodeIdentifier
("self"), "GObject *"));
- res_wrapper.add_argument (new CCodeConstant ("NULL"));
- res_wrapper.add_argument (new CCodeIdentifier ("_callback_"));
- res_wrapper.add_argument (new CCodeIdentifier ("_user_data_"));
- ccall.add_argument (res_wrapper);
-
- ccode.add_expression (ccall);
- }
-
- // free D-Bus message
-
- ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
- ccall.add_argument (new CCodeIdentifier ("_message"));
- ccode.add_expression (ccall);
- } else {
- var ccall = new CCodeFunctionCall (new CCodeIdentifier
("g_dbus_connection_send_message_with_reply_finish"));
- ccall.add_argument (connection);
-
- // unwrap async result
- ccode.add_declaration ("GAsyncResult", new CCodeVariableDeclarator ("*_inner_res"));
-
- var inner_res = new CCodeFunctionCall (new CCodeIdentifier
("g_task_propagate_pointer"));
- inner_res.add_argument (new CCodeCastExpression (new CCodeIdentifier ("_res_"),
"GTask *"));
- inner_res.add_argument (new CCodeConstant ("NULL"));
- ccode.add_assignment (new CCodeIdentifier ("_inner_res"), inner_res);
-
- ccall.add_argument (new CCodeIdentifier ("_inner_res"));
- ccall.add_argument (error_argument);
- ccode.add_assignment (new CCodeIdentifier ("_reply_message"), ccall);
-
- // _inner_res is guaranteed to be non-NULL, so just unref it
- var unref_inner_res = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
- unref_inner_res.add_argument (new CCodeIdentifier ("_inner_res"));
- ccode.add_expression (unref_inner_res);
- }
-
- if (call_type == CallType.SYNC || call_type == CallType.FINISH) {
- ccode.add_declaration ("GDBusMessage", new CCodeVariableDeclarator
("*_reply_message"));
-
- var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_object_unref"));
- unref_reply.add_argument (new CCodeIdentifier ("_reply_message"));
-
- // return on io error
- var reply_is_null = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION,
new CCodeIdentifier ("_reply_message"));
- ccode.open_if (reply_is_null);
- return_default_value (m.return_type);
- ccode.close ();
-
- // return on remote error
- var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_message_to_gerror"));
- ccall.add_argument (new CCodeIdentifier ("_reply_message"));
- ccall.add_argument (error_argument);
- ccode.open_if (ccall);
- ccode.add_expression (unref_reply);
- return_default_value (m.return_type);
- ccode.close ();
-
- bool has_result = !(m.return_type is VoidType);
-
- if (uses_fd) {
- ccode.add_declaration ("gint", new CCodeVariableDeclarator.zero ("_fd_index",
new CCodeConstant ("0")));
- ccode.add_declaration ("gint", new CCodeVariableDeclarator ("_fd"));
- }
-
- foreach (Parameter param in m.get_parameters ()) {
- if (param.direction == ParameterDirection.OUT) {
- has_result = true;
- }
- }
-
- if (has_result) {
- ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_reply"));
- ccode.add_declaration ("GVariantIter", new CCodeVariableDeclarator
("_reply_iter"));
-
- ccall = new CCodeFunctionCall (new CCodeIdentifier
("g_dbus_message_get_body"));
- ccall.add_argument (new CCodeIdentifier ("_reply_message"));
- ccode.add_assignment (new CCodeIdentifier ("_reply"), ccall);
-
- var iter_init = new CCodeFunctionCall (new CCodeIdentifier
("g_variant_iter_init"));
- iter_init.add_argument (new CCodeUnaryExpression
(CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("_reply_iter")));
- iter_init.add_argument (new CCodeIdentifier ("_reply"));
- ccode.add_expression (iter_init);
-
- foreach (Parameter param in m.get_parameters ()) {
- if (param.direction == ParameterDirection.OUT) {
- ccode.add_declaration (get_ccode_name (param.variable_type),
new CCodeVariableDeclarator.zero ("_vala_%s".printf (param.name), default_value_for_type
(param.variable_type, true)));
-
- var array_type = param.variable_type as ArrayType;
-
- if (array_type != null) {
- for (int dim = 1; dim <= array_type.rank; dim++) {
- ccode.add_declaration ("int", new
CCodeVariableDeclarator ("_vala_%s_length%d".printf (param.name, dim), new CCodeConstant ("0")));
- }
- }
-
- var target = new CCodeIdentifier ("_vala_%s".printf
(param.name));
- bool may_fail;
-
- receive_dbus_value (param.variable_type, new CCodeIdentifier
("_reply_message"), new CCodeIdentifier ("_reply_iter"), target, param, error_argument, out may_fail);
-
- // TODO check that parameter is not NULL (out parameters are
optional)
- // free value if parameter is NULL
- ccode.add_assignment (new CCodeUnaryExpression
(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier (get_variable_cname (param.name))), target);
-
- if (array_type != null) {
- for (int dim = 1; dim <= array_type.rank; dim++) {
- // TODO check that parameter is not NULL (out
parameters are optional)
- ccode.add_assignment (new
CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("%s_length%d".printf
(param.name, dim))), new CCodeIdentifier ("_vala_%s_length%d".printf (param.name, dim)));
- }
- }
-
- if (may_fail && has_error_argument) {
- ccode.open_if (new CCodeBinaryExpression
(CCodeBinaryOperator.AND, new CCodeIdentifier ("error"), new CCodeUnaryExpression
(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error"))));
- ccode.add_expression (unref_reply);
- return_default_value (m.return_type);
- ccode.close ();
- }
- }
- }
-
- if (!(m.return_type is VoidType)) {
- if (m.return_type.is_real_non_null_struct_type ()) {
- var target = new CCodeUnaryExpression
(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result"));
- receive_dbus_value (m.return_type, new CCodeIdentifier
("_reply_message"), new CCodeIdentifier ("_reply_iter"), target, m);
- } else {
- ccode.add_declaration (get_ccode_name (m.return_type), new
CCodeVariableDeclarator.zero ("_result", default_value_for_type (m.return_type, true)));
-
- var array_type = m.return_type as ArrayType;
-
- if (array_type != null) {
- for (int dim = 1; dim <= array_type.rank; dim++) {
- ccode.add_declaration ("int", new
CCodeVariableDeclarator ("_result_length%d".printf (dim), new CCodeConstant ("0")));
- }
- }
-
- bool may_fail;
- receive_dbus_value (m.return_type, new CCodeIdentifier
("_reply_message"), new CCodeIdentifier ("_reply_iter"), new CCodeIdentifier ("_result"), m, new
CCodeIdentifier ("error"), out may_fail);
-
- if (array_type != null) {
- for (int dim = 1; dim <= array_type.rank; dim++) {
- // TODO check that parameter is not NULL (out
parameters are optional)
- ccode.add_assignment (new
CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length%d".printf
(dim))), new CCodeIdentifier ("_result_length%d".printf (dim)));
- }
- }
-
- if (may_fail) {
- ccode.open_if (new CCodeBinaryExpression
(CCodeBinaryOperator.AND, new CCodeIdentifier ("error"), new CCodeUnaryExpression
(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("error"))));
- ccode.add_expression (unref_reply);
- return_default_value (m.return_type);
- ccode.close ();
- }
- }
- }
- }
-
- ccode.add_expression (unref_reply);
-
- if (!(m.return_type is VoidType || m.return_type.is_real_non_null_struct_type ())) {
- ccode.add_return (new CCodeIdentifier ("_result"));
- }
- }
- }
-
- string generate_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
- string proxy_name = "%sproxy_%s".printf (get_ccode_lower_case_prefix (main_iface), m.name);
-
- string dbus_iface_name = get_dbus_name (iface);
-
- bool no_reply = is_dbus_no_reply (m);
-
- var function = new CCodeFunction (proxy_name);
- function.modifiers = CCodeModifiers.STATIC;
-
- var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
-
- generate_cparameters (m, cfile, cparam_map, function);
-
- push_function (function);
-
- generate_marshalling (m, no_reply ? CallType.NO_REPLY : CallType.SYNC, dbus_iface_name,
get_dbus_name_for_member (m), get_dbus_timeout_for_member (m));
-
- pop_function ();
-
- cfile.add_function_declaration (function);
- cfile.add_function (function);
-
- return proxy_name;
- }
-
- string generate_async_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
- string proxy_name = "%sproxy_%s_async".printf (get_ccode_lower_case_prefix (main_iface),
m.name);
-
- string dbus_iface_name = get_dbus_name (iface);
-
- var function = new CCodeFunction (proxy_name, "void");
- function.modifiers = CCodeModifiers.STATIC;
-
- var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
-
- cparam_map.set (get_param_pos (-1), new CCodeParameter ("_callback_", "GAsyncReadyCallback"));
- cparam_map.set (get_param_pos (-0.9), new CCodeParameter ("_user_data_", "gpointer"));
-
- generate_cparameters (m, cfile, cparam_map, function, null, null, null, 1);
-
- push_function (function);
-
- generate_marshalling (m, CallType.ASYNC, dbus_iface_name, get_dbus_name_for_member (m),
get_dbus_timeout_for_member (m));
-
- pop_function ();
-
- cfile.add_function_declaration (function);
- cfile.add_function (function);
-
- return proxy_name;
- }
-
- string generate_finish_dbus_proxy_method (Interface main_iface, Interface iface, Method m) {
- string proxy_name = "%sproxy_%s_finish".printf (get_ccode_lower_case_prefix (main_iface),
m.name);
-
- var function = new CCodeFunction (proxy_name);
- function.modifiers = CCodeModifiers.STATIC;
-
- var cparam_map = new HashMap<int,CCodeParameter> (direct_hash, direct_equal);
-
- cparam_map.set (get_param_pos (0.1), new CCodeParameter ("_res_", "GAsyncResult*"));
-
- generate_cparameters (m, cfile, cparam_map, function, null, null, null, 2);
-
- push_function (function);
-
- generate_marshalling (m, CallType.FINISH, null, null, -1);
-
- pop_function ();
-
- cfile.add_function_declaration (function);
- cfile.add_function (function);
-
- return proxy_name;
- }
-
- string generate_dbus_proxy_property_get (Interface main_iface, Interface iface, Property prop) {
- string proxy_name = "%sdbus_proxy_get_%s".printf (get_ccode_lower_case_prefix (main_iface),
prop.name);
-
- string dbus_iface_name = get_dbus_name (iface);
-
- var owned_type = prop.get_accessor.value_type.copy ();
- owned_type.value_owned = true;
- if (owned_type.is_disposable () && !prop.get_accessor.value_type.value_owned) {
- Report.error (prop.get_accessor.value_type.source_reference, "Properties used in
D-Bus clients require owned get accessor");
- }
-
- var array_type = prop.get_accessor.value_type as ArrayType;
-
- var function = new CCodeFunction (proxy_name);
- function.modifiers = CCodeModifiers.STATIC;
-
- function.add_parameter (new CCodeParameter ("self", "%s*".printf (get_ccode_name (iface))));
-
- if (prop.property_type.is_real_non_null_struct_type ()) {
- function.add_parameter (new CCodeParameter ("result", "%s*".printf (get_ccode_name
(prop.get_accessor.value_type))));
- } else {
- if (array_type != null) {
- for (int dim = 1; dim <= array_type.rank; dim++) {
- function.add_parameter (new CCodeParameter ("result_length%d".printf
(dim), "int*"));
- }
- }
-
- function.return_type = get_ccode_name (prop.get_accessor.value_type);
- }
-
- push_function (function);
-
- ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_inner_reply"));
-
- // first try cached value
- var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_get_cached_property"));
- ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *"));
- ccall.add_argument (new CCodeConstant ("\"%s\"".printf (get_dbus_name_for_member (prop))));
- ccode.add_assignment (new CCodeIdentifier ("_inner_reply"), ccall);
-
- // if not successful, retrieve value via D-Bus
- ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new
CCodeIdentifier ("_inner_reply")));
-
- ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
- ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_reply"));
- ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
-
- var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
- builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new
CCodeIdentifier ("_arguments_builder")));
- builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
- ccode.add_expression (builder_init);
-
- // interface name
- write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant
("\"%s\"".printf (dbus_iface_name)), null);
- // property name
- write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant
("\"%s\"".printf (get_dbus_name_for_member (prop))), null);
-
- var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
- builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new
CCodeIdentifier ("_arguments_builder")));
- ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
-
- ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_call_sync"));
- ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *"));
- ccall.add_argument (new CCodeConstant ("\"org.freedesktop.DBus.Properties.Get\""));
- ccall.add_argument (new CCodeIdentifier ("_arguments"));
- ccall.add_argument (new CCodeConstant ("G_DBUS_CALL_FLAGS_NONE"));
- ccall.add_argument (get_dbus_timeout (prop));
- ccall.add_argument (new CCodeConstant ("NULL"));
- ccall.add_argument (new CCodeConstant ("NULL"));
-
- ccode.add_assignment (new CCodeIdentifier ("_reply"), ccall);
-
- // return on error
- ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new
CCodeIdentifier ("_reply")));
- return_default_value (prop.property_type);
- ccode.close ();
-
- var get_variant = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get"));
- get_variant.add_argument (new CCodeIdentifier ("_reply"));
- get_variant.add_argument (new CCodeConstant ("\"(v)\""));
- get_variant.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new
CCodeIdentifier ("_inner_reply")));
- ccode.add_expression (get_variant);
-
- var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
- unref_reply.add_argument (new CCodeIdentifier ("_reply"));
- ccode.add_expression (unref_reply);
-
- ccode.close ();
-
- if (prop.property_type.is_real_non_null_struct_type ()) {
- var target = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new
CCodeIdentifier ("result"));
- var result = deserialize_expression (prop.get_accessor.value_type, new
CCodeIdentifier ("_inner_reply"), target);
- ccode.add_assignment (target, result);
- } else {
- ccode.add_declaration (get_ccode_name (prop.get_accessor.value_type), new
CCodeVariableDeclarator ("_result"));
-
- if (get_dbus_signature (prop) != null) {
- // raw GVariant
- ccode.add_assignment (new CCodeIdentifier ("_result"), new
CCodeIdentifier("_inner_reply"));
- } else {
- if (array_type != null) {
- for (int dim = 1; dim <= array_type.rank; dim++) {
- ccode.add_declaration ("int", new CCodeVariableDeclarator
("_result_length%d".printf (dim), new CCodeConstant ("0")));
- }
- }
-
- var result = deserialize_expression (prop.get_accessor.value_type, new
CCodeIdentifier ("_inner_reply"), new CCodeIdentifier ("_result"));
- ccode.add_assignment (new CCodeIdentifier ("_result"), result);
-
- if (array_type != null) {
- for (int dim = 1; dim <= array_type.rank; dim++) {
- // TODO check that parameter is not NULL (out parameters are
optional)
- ccode.add_assignment (new CCodeUnaryExpression
(CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier ("result_length%d".printf (dim))), new
CCodeIdentifier ("_result_length%d".printf (dim)));
- }
- }
- }
- }
-
- if (prop.property_type.is_real_non_null_struct_type () || get_dbus_signature (prop) == null) {
- unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
- unref_reply.add_argument (new CCodeIdentifier ("_inner_reply"));
- ccode.add_expression (unref_reply);
- }
-
- if (prop.property_type.is_real_non_null_struct_type ()) {
- ccode.add_return ();
- } else {
- ccode.add_return (new CCodeIdentifier ("_result"));
- }
-
- pop_function ();
-
- cfile.add_function_declaration (function);
- cfile.add_function (function);
-
- return proxy_name;
- }
-
- string generate_dbus_proxy_property_set (Interface main_iface, Interface iface, Property prop) {
- string proxy_name = "%sdbus_proxy_set_%s".printf (get_ccode_lower_case_prefix (main_iface),
prop.name);
-
- string dbus_iface_name = get_dbus_name (iface);
-
- var array_type = prop.set_accessor.value_type as ArrayType;
-
- var function = new CCodeFunction (proxy_name);
- function.modifiers = CCodeModifiers.STATIC;
-
- function.add_parameter (new CCodeParameter ("self", "%s*".printf (get_ccode_name (iface))));
-
- if (prop.property_type.is_real_non_null_struct_type ()) {
- function.add_parameter (new CCodeParameter ("value", "%s*".printf (get_ccode_name
(prop.set_accessor.value_type))));
- } else {
- function.add_parameter (new CCodeParameter ("value", get_ccode_name
(prop.set_accessor.value_type)));
-
- if (array_type != null) {
- for (int dim = 1; dim <= array_type.rank; dim++) {
- function.add_parameter (new CCodeParameter ("value_length%d".printf
(dim), "int"));
- }
- }
- }
-
- push_function (function);
-
- ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_arguments"));
- ccode.add_declaration ("GVariant", new CCodeVariableDeclarator ("*_reply"));
-
- ccode.add_declaration ("GVariantBuilder", new CCodeVariableDeclarator ("_arguments_builder"));
-
- var builder_init = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_init"));
- builder_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new
CCodeIdentifier ("_arguments_builder")));
- builder_init.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_TUPLE"));
- ccode.add_expression (builder_init);
-
- // interface name
- write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant
("\"%s\"".printf (dbus_iface_name)), null);
- // property name
- write_expression (string_type, new CCodeIdentifier ("_arguments_builder"), new CCodeConstant
("\"%s\"".printf (get_dbus_name_for_member (prop))), null);
-
- // property value (as variant)
- var builder_open = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_open"));
- builder_open.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new
CCodeIdentifier ("_arguments_builder")));
- builder_open.add_argument (new CCodeIdentifier ("G_VARIANT_TYPE_VARIANT"));
- ccode.add_expression (builder_open);
-
- if (prop.property_type.is_real_non_null_struct_type ()) {
- write_expression (prop.set_accessor.value_type, new CCodeIdentifier
("_arguments_builder"), new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, new CCodeIdentifier
("value")), prop);
- } else {
- write_expression (prop.set_accessor.value_type, new CCodeIdentifier
("_arguments_builder"), new CCodeIdentifier ("value"), prop);
- }
-
- var builder_close = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_close"));
- builder_close.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new
CCodeIdentifier ("_arguments_builder")));
- ccode.add_expression (builder_close);
-
- var builder_end = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_builder_end"));
- builder_end.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new
CCodeIdentifier ("_arguments_builder")));
- ccode.add_assignment (new CCodeIdentifier ("_arguments"), builder_end);
-
- var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_proxy_call_sync"));
- ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier ("self"), "GDBusProxy *"));
- ccall.add_argument (new CCodeConstant ("\"org.freedesktop.DBus.Properties.Set\""));
- ccall.add_argument (new CCodeIdentifier ("_arguments"));
- ccall.add_argument (new CCodeConstant ("G_DBUS_CALL_FLAGS_NONE"));
- ccall.add_argument (get_dbus_timeout (prop));
- ccall.add_argument (new CCodeConstant ("NULL"));
- ccall.add_argument (new CCodeConstant ("NULL"));
-
- ccode.add_assignment (new CCodeIdentifier ("_reply"), ccall);
-
- // return on error
- ccode.open_if (new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, new
CCodeIdentifier ("_reply")));
- ccode.add_return ();
- ccode.close ();
-
- var unref_reply = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_unref"));
- unref_reply.add_argument (new CCodeIdentifier ("_reply"));
- ccode.add_expression (unref_reply);
-
- pop_function ();
-
- cfile.add_function_declaration (function);
- cfile.add_function (function);
-
- return proxy_name;
- }
-
public override void register_dbus_info (CCodeBlock block, ObjectTypeSymbol sym) {
if (!(sym is Interface)) {
return;
diff --git a/codegen/valagdbusclienttransformer.vala b/codegen/valagdbusclienttransformer.vala
new file mode 100644
index 000000000..5e8b9da2a
--- /dev/null
+++ b/codegen/valagdbusclienttransformer.vala
@@ -0,0 +1,347 @@
+/* valagdbusclienttransformer.vala
+ *
+ * Copyright (C) 2011 Luca Bruno
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Luca Bruno <lucabru src gnome org>
+ */
+
+/**
+ * Code visitor for transforming the code tree related to DBus clients.
+ */
+public class Vala.GDBusClientTransformer : GVariantTransformer {
+ public static bool is_dbus_no_reply (Method m) {
+ return m.get_attribute_bool ("DBus", "no_reply");
+ }
+
+ public static string? get_dbus_name (TypeSymbol symbol) {
+ return symbol.get_attribute_string ("DBus", "name");
+ }
+
+ public static string get_dbus_name_for_member (Symbol symbol) {
+ var dbus_name = symbol.get_attribute_string ("DBus", "name");
+ if (dbus_name != null) {
+ return dbus_name;
+ }
+
+ return Symbol.lower_case_to_camel_case (symbol.name);
+ }
+
+ Expression read_dbus_value (DataType type, string iter, string message, ref string? fd_list, ref
string? fd_index) {
+ string? type_name = null;
+ if (type.data_type != null) {
+ type_name = type.data_type.get_full_name ();
+ }
+ if (type_name == "GLib.UnixInputStream" || type_name == "GLib.UnixOutputStream" || type_name
== "GLib.Socket") {
+ if (fd_list == null) {
+ fd_list = b.add_temp_declaration (data_type ("GLib.UnixFDList"), null);
+ fd_index = b.add_temp_declaration (null, expression ("0"));
+ b.add_expression (expression (@"$fd_list = $message.get_unix_fd_list ()"));
+ }
+ b.add_expression (expression (@"$iter.next (\"h\", out $fd_index)"));
+ if (type_name == "GLib.UnixInputStream") {
+ return expression (@"new GLib.UnixInputStream ($fd_list.get ($fd_index),
true)");
+ } else if (type_name == "GLib.UnixOutputStream") {
+ return expression (@"new GLib.UnixOutputStream ($fd_list.get ($fd_index),
true)");
+ } else {
+ // socket
+ return expression (@"new GLib.Socket.from_fd ($fd_list.get ($fd_index))");
+ }
+ } else {
+ return expression (@"($(type)) ($iter.next_value ())");
+ }
+ }
+
+ void generate_marshalling (Method m, string? iface_name, string? method_name, int method_timeout) {
+ var interface_name = iface_name != null ? @"\"$iface_name\"" : "this.get_interface_name ()";
+
+ // create the message
+ var reply = b.add_temp_declaration (data_type ("GLib.DBusMessage"));
+ var message = b.add_temp_declaration (null, expression (@"new GLib.DBusMessage.method_call
(this.get_name(), this.get_object_path (), $interface_name, \"$method_name\")"));
+ var builder = b.add_temp_declaration (null, expression (@"new GLib.VariantBuilder
(GLib.VariantType.TUPLE)"));
+
+ // fill the message
+ bool has_result = m.has_result;
+ string cancellable = "null";
+ string fd_list = null;
+ foreach (var param in m.get_parameters ()) {
+ if (param.direction == ParameterDirection.IN) {
+ string? type_name = null;
+ if (param.variable_type.data_type != null) {
+ type_name = param.variable_type.data_type.get_full_name ();
+ }
+ if (type_name == "GLib.Cancellable") {
+ cancellable = param.name;
+ } else if (type_name == "GLib.BusName") {
+ // ignore BusName sender
+ } else if (type_name == "GLib.UnixInputStream" || type_name ==
"GLib.UnixOutputStream" || type_name == "GLib.Socket") {
+ if (fd_list == null) {
+ fd_list = b.add_temp_declaration (null, expression ("new
GLib.UnixFDList ()"));
+ }
+ b.add_expression (expression (@"$builder.add (\"h\", $fd_list.append
($(param.name).get_fd ()))"));
+ } else {
+ b.add_expression (expression (@"$builder.add_value ($(param.name))"));
+ }
+ } else if (param.direction == ParameterDirection.OUT) {
+ has_result = true;
+ }
+ }
+ b.add_expression (expression (@"$message.set_body ($builder.end ())"));
+ if (fd_list != null) {
+ b.add_expression (expression (@"$message.set_unix_fd_list ($fd_list)"));
+ }
+
+ // send the message
+ if (is_dbus_no_reply (m)) {
+ b.add_expression (expression (@"this.get_connection().send_message ($message,
GLib.DBusSendMessageFlags.NO_REPLY_EXPECTED, null)"));
+ } else {
+ var yield_str = m.coroutine ? "yield " : "";
+ var method_str = m.coroutine ? "send_message_with_reply" :
"send_message_with_reply_sync";
+ var timeout_str = method_timeout > 0 ? @"$method_timeout" : "this.get_default_timeout
()";
+ b.add_expression (expression (@"$reply = $yield_str this.get_connection().$method_str
($message, GLib.DBusSendMessageFlags.NONE, $timeout_str, null, $cancellable)"));
+
+ b.add_expression (expression (@"$reply.to_gerror ()"));
+ }
+
+ // deserialize the result
+ fd_list = null;
+ string fd_index = null;
+ if (has_result) {
+ var iter = b.add_temp_declaration (data_type ("GLib.VariantIter"));
+ b.add_expression (expression (@"$iter = $reply.get_body().iterator ()"));
+ foreach (var param in m.get_parameters ()) {
+ if (param.direction == ParameterDirection.OUT) {
+ b.add_assignment (expression (param.name), read_dbus_value
(param.variable_type, iter, reply, ref fd_list, ref fd_index));
+ }
+ }
+ if (m.has_result) {
+ b.add_return (read_dbus_value (m.return_type, iter, reply, ref fd_list, ref
fd_index));
+ }
+ }
+ }
+
+ void generate_dbus_proxy_method (Class proxy_class, Interface iface, Method m) {
+ var proxy = new Method (m.name, m.return_type, m.source_reference);
+ foreach (var param in m.get_parameters ()) {
+ proxy.add_parameter (param.copy ());
+ }
+ proxy.access = m.access;
+ proxy.binding = m.binding;
+ proxy.coroutine = m.coroutine;
+ var error_types = new ArrayList<DataType> ();
+ m.get_error_types (error_types);
+ foreach (var error_type in error_types) {
+ proxy.add_error_type (error_type);
+ }
+ proxy_class.add_method (proxy);
+
+ b = new CodeBuilder.for_subroutine (proxy);
+ string dbus_iface_name = get_dbus_name (iface);
+ generate_marshalling (m, dbus_iface_name, get_dbus_name_for_member (m),
GDBusModule.get_dbus_timeout_for_member (m));
+ }
+
+ void generate_dbus_proxy_methods (Class proxy_class, Interface iface) {
+ // also generate proxy for prerequisites
+ foreach (var prereq in iface.get_prerequisites ()) {
+ if (prereq.data_type is Interface) {
+ generate_dbus_proxy_methods (proxy_class, (Interface) prereq.data_type);
+ }
+ }
+
+ foreach (var m in iface.get_methods ()) {
+ if (!m.is_abstract) {
+ continue;
+ }
+
+ generate_dbus_proxy_method (proxy_class, iface, m);
+ }
+ }
+
+ string generate_dbus_proxy_signal (Class proxy_class, Signal sig, ObjectTypeSymbol sym) {
+ var m = new Method (temp_func_cname (), new VoidType (), sig.source_reference);
+ m.access = SymbolAccessibility.PRIVATE;
+ m.add_parameter (new Parameter ("parameters", data_type ("GLib.Variant", false),
sig.source_reference));
+ proxy_class.add_method (m);
+ b.push_method (m);
+
+ var iter = b.add_temp_declaration (null, expression ("parameters.iterator ()"));
+ var call = new MethodCall (expression (sig.name), sig.source_reference);
+ foreach (var param in sig.get_parameters ()) {
+ var temp = b.add_temp_declaration (copy_type (param.variable_type, true));
+ if (param.variable_type.data_type == context.analyzer.gvariant_type.data_type) {
+ b.add_expression (expression (@"$temp = $iter.next_value().get_variant ()"));
+ } else {
+ b.add_expression (expression (@"$temp = ($(param.variable_type))
($iter.next_value ())"));
+ }
+ call.add_argument (expression (temp));
+ }
+ b.add_expression (call);
+
+ b.pop_method ();
+ return m.name;
+ }
+
+ void generate_dbus_proxy_signals (Class proxy_class, ObjectTypeSymbol sym) {
+ var g_signal = (Signal) symbol_from_string ("GLib.DBusProxy.g_signal");
+ var m = new Method ("g_signal", g_signal.return_type, sym.source_reference);
+ m.overrides = true;
+ m.access = SymbolAccessibility.PUBLIC;
+ foreach (var param in g_signal.get_parameters ()) {
+ m.add_parameter (param.copy ());
+ }
+ proxy_class.add_method (m);
+
+ b = new CodeBuilder.for_subroutine (m);
+
+ b.open_switch (expression ("signal_name"), null);
+ b.add_expression (expression ("assert_not_reached ()"));
+ b.add_break ();
+ foreach (var sig in sym.get_signals ()) {
+ if (sig.access != SymbolAccessibility.PUBLIC) {
+ continue;
+ }
+
+ b.add_section (expression (@"\"$(get_dbus_name_for_member (sig))\""));
+ var handler_name = generate_dbus_proxy_signal (proxy_class, sig, sym);
+ b.add_expression (expression (@"$handler_name (parameters)"));
+ b.add_break ();
+ }
+ b.close ();
+ }
+
+ public int get_dbus_timeout (Symbol symbol) {
+ int timeout = -1;
+
+ var dbus = symbol.get_attribute ("DBus");
+ if (dbus != null && dbus.has_argument ("timeout")) {
+ timeout = dbus.get_integer ("timeout");
+ } else if (symbol.parent_symbol != null) {
+ return get_dbus_timeout (symbol.parent_symbol);
+ }
+
+ return timeout;
+ }
+
+ void generate_dbus_proxy_property (Class proxy_class, Interface iface, Property prop) {
+ int timeout = get_dbus_timeout (prop);
+ var dbus_name = get_dbus_name_for_member (prop);
+ var dbus_iface_name = get_dbus_name (iface);
+
+ PropertyAccessor proxy_get = null;
+ if (prop.get_accessor != null) {
+ var owned_type = copy_type (prop.get_accessor.value_type, true);
+ if (owned_type.is_disposable () && !prop.get_accessor.value_type.value_owned) {
+ Report.error (prop.get_accessor.value_type.source_reference, "Properties used
in D-Bus clients require owned get accessor");
+ return;
+ }
+
+ proxy_get = new PropertyAccessor (true, false, false, owned_type, null,
prop.get_accessor.source_reference);
+
+ b = new CodeBuilder.for_subroutine (proxy_get);
+ // first try cached value
+ var result = b.add_temp_declaration (null, expression (@"get_cached_property
(\"$dbus_name\")"));
+ b.open_if (expression (@"$result == null"));
+ b.add_expression (expression (@"$result = call_sync
(\"org.freedesktop.DBus.Properties.Get\", new Variant (\"(ss)\", \"$dbus_iface_name\", \"$dbus_name\"),
GLib.DBusCallFlags.NONE, $timeout, null)"));
+ b.add_expression (expression (@"$result.get (\"(v)\", out $result)"));
+ b.close ();
+
+ b.add_return (expression (@"($(prop.property_type)) ($result)"));
+ }
+
+ PropertyAccessor proxy_set = null;
+ if (prop.set_accessor != null) {
+ proxy_set = new PropertyAccessor (false, true, false, prop.set_accessor.value_type,
null, prop.set_accessor.source_reference);
+ b = new CodeBuilder.for_subroutine (proxy_set);
+ var variant = b.add_temp_declaration (data_type ("GLib.Variant"), expression
("value"));
+ b.add_expression (expression (@"call_sync (\"org.freedesktop.DBus.Properties.Set\",
new Variant (\"(ssv)\", \"$dbus_iface_name\", \"$dbus_name\", $variant), GLib.DBusCallFlags.NONE, $timeout,
null)"));
+ }
+
+ Property proxy = new Property (prop.name, prop.property_type, proxy_get, proxy_set,
prop.source_reference);
+ proxy_class.add_property (proxy);
+ }
+
+ void generate_dbus_proxy_properties (Class proxy_class, Interface iface) {
+ // also generate proxy for prerequisites
+ foreach (var prereq in iface.get_prerequisites ()) {
+ if (prereq.data_type is Interface) {
+ generate_dbus_proxy_properties (proxy_class, (Interface) prereq.data_type);
+ }
+ }
+
+ foreach (var prop in iface.get_properties ()) {
+ if (!prop.is_abstract) {
+ continue;
+ }
+
+ generate_dbus_proxy_property (proxy_class, iface, prop);
+ }
+ }
+
+ public override void visit_interface (Interface iface) {
+ base.visit_interface (iface);
+
+ string dbus_iface_name = get_dbus_name (iface);
+ if (dbus_iface_name == null) {
+ return;
+ }
+
+ if (iface.parent_symbol.scope.lookup (iface.name+"Proxy") != null) {
+ return;
+ }
+
+ // create proxy class
+ var proxy = new Class (iface.name+"Proxy", iface.source_reference, null);
+ proxy.add_base_type (data_type ("GLib.DBusProxy"));
+ proxy.add_base_type (context.analyzer.get_data_type_for_symbol (iface));
+ proxy.access = iface.access;
+ iface.parent_symbol.add_class (proxy);
+
+ generate_dbus_proxy_methods (proxy, iface);
+ generate_dbus_proxy_signals (proxy, iface);
+ generate_dbus_proxy_properties (proxy, iface);
+
+ check (proxy);
+ }
+
+ public override void visit_method_call (MethodCall expr) {
+ var m = expr.call.symbol_reference as DynamicMethod;
+ if (m == null || m.dynamic_type.data_type != symbol_from_string ("GLib.DBusProxy")) {
+ // not a dynamic dbus call
+ base.visit_method_call (expr);
+ return;
+ }
+
+ b = new CodeBuilder (context, expr.parent_statement, expr.source_reference);
+
+ Method wrapper;
+ var cache_key = "gdbus_client_dynamic_method_call "+m.return_type.to_string ();
+ foreach (var param in m.get_parameters ()) {
+ cache_key = "%s %s".printf (cache_key, param.variable_type.to_string ());
+ }
+ if (!wrapper_method (m.return_type, cache_key, out wrapper, symbol_from_string
("GLib.DBusProxy"))) {
+ foreach (var param in m.get_parameters ()) {
+ wrapper.add_parameter (param.copy ());
+ }
+ b = new CodeBuilder.for_subroutine (wrapper);
+ generate_marshalling (m, null, m.name, GDBusModule.get_dbus_timeout_for_member (m));
+ check (wrapper);
+ }
+
+ expr.call.symbol_reference = wrapper;
+ base.visit_method_call (expr);
+ }
+}
diff --git a/codegen/valagvariantmodule.vala b/codegen/valagvariantmodule.vala
index faa36f03e..349f9f5cf 100644
--- a/codegen/valagvariantmodule.vala
+++ b/codegen/valagvariantmodule.vala
@@ -49,14 +49,6 @@ public class Vala.GVariantModule : GAsyncModule {
return false;
}
- string get_dbus_value (EnumValue value, string default_value) {
- var dbus_value = value.get_attribute_string ("DBus", "value");
- if (dbus_value != null) {
- return dbus_value;;
- }
- return default_value;
- }
-
public static string? get_dbus_signature (Symbol symbol) {
return symbol.get_attribute_string ("DBus", "signature");
}
diff --git a/codegen/valagvarianttransformer.vala b/codegen/valagvarianttransformer.vala
index ff41b4cc7..8770a5312 100644
--- a/codegen/valagvarianttransformer.vala
+++ b/codegen/valagvarianttransformer.vala
@@ -416,7 +416,7 @@ public class Vala.GVariantTransformer : CodeTransformer {
en.add_method (m);
m.binding = MemberBinding.STATIC;
m.access = SymbolAccessibility.PUBLIC;
- b = new CodeBuilder.for_method (m);
+ b = new CodeBuilder.for_subroutine (m);
b.open_switch (expression ("str"), null);
b.add_throw (expression ("new GLib.DBusError.INVALID_ARGS (\"Invalid value for enum
`%s'\")".printf (get_ccode_name (en))));
@@ -437,7 +437,7 @@ public class Vala.GVariantTransformer : CodeTransformer {
var m = new Method ("to_string", data_type ("string", false, true), en.source_reference);
en.add_method (m);
m.access = SymbolAccessibility.PUBLIC;
- b = new CodeBuilder.for_method (m);
+ b = new CodeBuilder.for_subroutine (m);
b.open_switch (expression ("this"), null);
b.add_return (expression ("null"));
diff --git a/compiler/valacompiler.vala b/compiler/valacompiler.vala
index 8624c5576..f2010d5ee 100644
--- a/compiler/valacompiler.vala
+++ b/compiler/valacompiler.vala
@@ -415,7 +415,7 @@ class Vala.Compiler {
}
}
- var transformer = new GVariantTransformer ();
+ var transformer = new GDBusClientTransformer ();
transformer.transform (context);
if (context.report.get_errors () > 0 || (fatal_warnings && context.report.get_warnings () >
0)) {
diff --git a/vala/valacodebuilder.vala b/vala/valacodebuilder.vala
index 73a18f94e..c10ffbae1 100644
--- a/vala/valacodebuilder.vala
+++ b/vala/valacodebuilder.vala
@@ -48,7 +48,7 @@ public class Vala.CodeBuilder {
build_context.check_nodes.add (build_context.current_block);
}
- public CodeBuilder.for_method (Method m) {
+ public CodeBuilder.for_subroutine (Subroutine m) {
source_reference = m.source_reference;
build_context = new BuildContext ();
build_context.insert_block = m.body = new Block (source_reference);
diff --git a/vala/valacodetransformer.vala b/vala/valacodetransformer.vala
index 77c0dec6e..c60f04f89 100644
--- a/vala/valacodetransformer.vala
+++ b/vala/valacodetransformer.vala
@@ -62,16 +62,18 @@ public class Vala.CodeTransformer : CodeVisitor {
wrapper_cache.set (key, node);
}
- public bool wrapper_method (DataType return_type, string cache_key, out Method m) {
- CodeNode n;
- if (get_cached_wrapper (cache_key, out n)) {
+ public string temp_func_cname () {
+ return "_vala_func_"+CodeNode.get_temp_name ().substring (1);
+ }
+
+ public bool wrapper_method (DataType return_type, string? cache_key, out Method m, Symbol? parent =
null) {
+ CodeNode n = null;
+ if (cache_key != null && get_cached_wrapper (cache_key, out n)) {
m = (Method) n;
return true;
}
- var name = CodeNode.get_temp_name ().replace (".", "");
- name = "_vala_func_"+name;
- m = new Method (name, return_type, b.source_reference);
- context.root.add_method (m);
+ m = new Method (temp_func_cname (), return_type, b.source_reference);
+ (parent == null ? context.root : parent).add_method (m);
m.access = SymbolAccessibility.PRIVATE;
add_cached_wrapper (cache_key, m);
return false;
diff --git a/vapi/gio-2.0.vapi b/vapi/gio-2.0.vapi
index 7127a5925..982773bd5 100644
--- a/vapi/gio-2.0.vapi
+++ b/vapi/gio-2.0.vapi
@@ -832,7 +832,7 @@ namespace GLib {
public DBusMessage.@signal (string path, string interface_, string @signal);
[CCode (array_length_pos = 0.5, array_length_type = "gsize")]
public uint8[] to_blob (GLib.DBusCapabilityFlags capabilities) throws GLib.Error;
- public bool to_gerror () throws GLib.Error;
+ public bool to_gerror () throws GLib.IOError;
public bool locked { get; }
}
[CCode (cheader_filename = "gio/gio.h", ref_function = "g_dbus_method_info_ref", type_id =
"g_dbus_method_info_get_type ()", unref_function = "g_dbus_method_info_unref")]
diff --git a/vapi/metadata/Gio-2.0.metadata b/vapi/metadata/Gio-2.0.metadata
index 1be074f95..e4752f0ba 100644
--- a/vapi/metadata/Gio-2.0.metadata
+++ b/vapi/metadata/Gio-2.0.metadata
@@ -107,6 +107,7 @@ DBusMessage
.new_method_error printf_format
.get_header_fields type="uchar[]"
.print.indent default=0
+ .to_gerror throws="GLib.IOError"
DBus*Info
.*#field unowned=false
DBus*VTable
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]