Commit 7ef89124 authored by Jürg Billeter's avatar Jürg Billeter Committed by Jürg Billeter

Improve support for dynamic types, add `dynamic' type modifier, port

2008-04-20  Juerg Billeter  <j@bitron.ch>

	* vala/Makefile.am, vala/valaclasstype.vala,
	  vala/valacodecontext.vala, vala/valacodegenerator.vala,
	  vala/valadatatype.vala, vala/valadynamicmethod.vala,
	  vala/valadynamicsignal.vala, vala/valainterface.vala,
	  vala/valainterfacetype.vala, vala/valamethod.vala,
	  vala/valamethodtype.vala, vala/valaparser.vala,
	  vala/valascanner.vala, vala/valasemanticanalyzer.vala,
	  vala/valasymbolresolver.vala, vala/valatokentype.vala,
	  vala/valaunresolvedtype.vala, vala/valavaluetype.vala,
	  gobject/Makefile.am, gobject/valaccodeassignmentbinding.vala,
	  gobject/valaccodebinding.vala,
	  gobject/valaccodedynamicmethodbinding.vala,
	  gobject/valaccodedynamicsignalbinding.vala,
	  gobject/valaccodegenerator.vala,
	  gobject/valaccodegeneratorsourcefile.vala,
	  gobject/valaccodeinterfacebinding.vala,
	  gobject/valaccodeinvocationexpressionbinding.vala,
	  gobject/valaccodemethodbinding.vala, compiler/valacompiler.vala,
	  vapi/dbus-glib-1.vapi:

	  Improve support for dynamic types, add `dynamic' type modifier,
	  port dynamic D-Bus client support

svn path=/trunk/; revision=1288
parent bb54ceb5
2008-04-20 Jürg Billeter <j@bitron.ch>
* vala/Makefile.am, vala/valaclasstype.vala,
vala/valacodecontext.vala, vala/valacodegenerator.vala,
vala/valadatatype.vala, vala/valadynamicmethod.vala,
vala/valadynamicsignal.vala, vala/valainterface.vala,
vala/valainterfacetype.vala, vala/valamethod.vala,
vala/valamethodtype.vala, vala/valaparser.vala,
vala/valascanner.vala, vala/valasemanticanalyzer.vala,
vala/valasymbolresolver.vala, vala/valatokentype.vala,
vala/valaunresolvedtype.vala, vala/valavaluetype.vala,
gobject/Makefile.am, gobject/valaccodeassignmentbinding.vala,
gobject/valaccodebinding.vala,
gobject/valaccodedynamicmethodbinding.vala,
gobject/valaccodedynamicsignalbinding.vala,
gobject/valaccodegenerator.vala,
gobject/valaccodegeneratorsourcefile.vala,
gobject/valaccodeinterfacebinding.vala,
gobject/valaccodeinvocationexpressionbinding.vala,
gobject/valaccodemethodbinding.vala, compiler/valacompiler.vala,
vapi/dbus-glib-1.vapi:
Improve support for dynamic types, add `dynamic' type modifier,
port dynamic D-Bus client support
2008-04-20 Jürg Billeter <j@bitron.ch>
* vapi/packages/gtk+-2.0/: fix GtkDialog.vbox binding
......
......@@ -234,11 +234,7 @@ class Vala.Compiler : Object {
return quit ();
}
var dbus_binding_provider = new DBusBindingProvider ();
dbus_binding_provider.context = context;
var analyzer = new SemanticAnalyzer ();
analyzer.add_binding_provider (dbus_binding_provider);
analyzer.analyze (context);
if (Report.get_errors () > 0) {
......
......@@ -18,6 +18,8 @@ libvala_la_VALASOURCES = \
valaccodeclassbinding.vala \
valaccodecompiler.vala \
valaccodecreationmethodbinding.vala \
valaccodedynamicmethodbinding.vala \
valaccodedynamicsignalbinding.vala \
valaccodeelementaccessbinding.vala \
valaccodeexpressionbinding.vala \
valaccodegenerator.vala \
......@@ -30,9 +32,6 @@ libvala_la_VALASOURCES = \
valaccodemethodbinding.vala \
valaccodetypesymbolbinding.vala \
valaclassregisterfunction.vala \
valadbusbindingprovider.vala \
valadbusmethod.vala \
valadbussignal.vala \
valagidlwriter.vala \
valainterfaceregisterfunction.vala \
valatyperegisterfunction.vala \
......
......@@ -106,8 +106,8 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding {
bool disconnect = false;
if (assignment.operator == AssignmentOperator.ADD) {
if (sig is DBusSignal) {
connect_func = "dbus_g_proxy_connect_signal";
if (sig is DynamicSignal) {
connect_func = codegen.dynamic_signal_binding ((DynamicSignal) sig).get_connect_wrapper_name ();
} else {
connect_func = "g_signal_connect_object";
if (!m.instance) {
......@@ -115,8 +115,8 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding {
}
}
} else if (assignment.operator == AssignmentOperator.SUB) {
if (sig is DBusSignal) {
connect_func = "dbus_g_proxy_disconnect_signal";
if (sig is DynamicSignal) {
connect_func = codegen.dynamic_signal_binding ((DynamicSignal) sig).get_disconnect_wrapper_name ();
} else {
connect_func = "g_signal_handlers_disconnect_matched";
}
......@@ -136,8 +136,8 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding {
ccall.add_argument (new CCodeIdentifier ("self"));
}
if (sig is DBusSignal) {
// dbus_g_proxy_connect_signal or dbus_g_proxy_disconnect_signal
if (sig is DynamicSignal) {
// dynamic_signal_connect or dynamic_signal_disconnect
// second argument: signal name
ccall.add_argument (new CCodeConstant ("\"%s\"".printf (sig.name)));
......@@ -176,8 +176,8 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding {
}
// third resp. sixth argument: handler
if (sig is DBusSignal) {
// signal handler wrappers not used for D-Bus signals
if (sig is DynamicSignal) {
// signal handler wrappers not used for dynamic signals
ccall.add_argument (new CCodeCastExpression (new CCodeIdentifier (m.get_cname ()), "GCallback"));
m.cinstance_parameter_position = -1;
} else {
......@@ -186,7 +186,7 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding {
if (m.instance) {
// g_signal_connect_object or g_signal_handlers_disconnect_matched
// or dbus_g_proxy_connect_signal or dbus_g_proxy_disconnect_signal
// or dynamic_signal_connect or dynamic_signal_disconnect
// fourth resp. seventh argument: object/user_data
if (assignment.right is MemberAccess) {
......@@ -199,98 +199,21 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding {
} else if (assignment.right is LambdaExpression) {
ccall.add_argument (new CCodeIdentifier ("self"));
}
if (!disconnect) {
if (sig is DBusSignal) {
// dbus_g_proxy_connect_signal
if (!disconnect && !(sig is DynamicSignal)) {
// g_signal_connect_object
// fifth argument: free_data_func
ccall.add_argument (new CCodeConstant ("NULL"));
} else {
// g_signal_connect_object
// fifth argument: connect_flags
ccall.add_argument (new CCodeConstant ("0"));
}
// fifth argument: connect_flags
ccall.add_argument (new CCodeConstant ("0"));
}
} else {
// g_signal_connect or g_signal_handlers_disconnect_matched
// or dbus_g_proxy_connect_signal or dbus_g_proxy_disconnect_signal
// or dynamic_signal_connect or dynamic_signal_disconnect
// fourth resp. seventh argument: user_data
ccall.add_argument (new CCodeConstant ("NULL"));
if (sig is DBusSignal && !disconnect) {
// fifth argument: free_data_func
ccall.add_argument (new CCodeConstant ("NULL"));
}
}
codenode = ccall;
if (sig is DBusSignal && !disconnect) {
bool first = true;
foreach (FormalParameter param in m.get_parameters ()) {
if (first) {
// skip sender parameter
first = false;
continue;
}
sig.add_parameter (param.copy ());
}
sig.accept (codegen);
// FIXME should only be done once per marshaller
var register_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_object_register_marshaller"));
register_call.add_argument (new CCodeIdentifier (codegen.get_signal_marshaller_function (sig)));
register_call.add_argument (new CCodeIdentifier ("G_TYPE_NONE"));
var add_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_add_signal"));
if (ma.inner != null) {
add_call.add_argument ((CCodeExpression) ma.inner.ccodenode);
} else {
add_call.add_argument (new CCodeIdentifier ("self"));
}
add_call.add_argument (new CCodeConstant ("\"%s\"".printf (sig.name)));
first = true;
foreach (FormalParameter param in m.get_parameters ()) {
if (first) {
// skip sender parameter
first = false;
continue;
}
if (param.type_reference is ArrayType && ((ArrayType) param.type_reference).element_type.data_type != codegen.string_type.data_type) {
var array_type = (ArrayType) param.type_reference;
if (array_type.element_type.data_type.get_type_id () == null) {
Report.error (param.source_reference, "unsupported parameter type for D-Bus signals");
return;
}
var carray_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_collection"));
carray_type.add_argument (new CCodeConstant ("\"GArray\""));
carray_type.add_argument (new CCodeIdentifier (array_type.element_type.data_type.get_type_id ()));
register_call.add_argument (carray_type);
add_call.add_argument (carray_type);
} else {
if (param.type_reference.get_type_id () == null) {
Report.error (param.source_reference, "unsupported parameter type for D-Bus signals");
return;
}
register_call.add_argument (new CCodeIdentifier (param.type_reference.get_type_id ()));
add_call.add_argument (new CCodeIdentifier (param.type_reference.get_type_id ()));
}
}
register_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
add_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
var ccomma = new CCodeCommaExpression ();
ccomma.append_expression (register_call);
ccomma.append_expression (add_call);
ccomma.append_expression (ccall);
codenode = ccomma;
}
}
private string generate_signal_handler_wrapper (Method m, Signal sig) {
......
......@@ -34,7 +34,8 @@ public abstract class Vala.CCodeBinding : CodeBinding {
/**
* Generate code for this source code node.
*/
public abstract void emit ();
public virtual void emit () {
}
public CCodeIdentifier get_value_setter_function (DataType type_reference) {
if (type_reference.data_type != null) {
......
/* valaccodedynamicmethodbinding.vala
*
* Copyright (C) 2007-2008 Jürg Billeter
*
* 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:
* Jürg Billeter <j@bitron.ch>
*/
using GLib;
using Gee;
/**
* The link between a dynamic method and generated code.
*/
public class Vala.CCodeDynamicMethodBinding : CCodeMethodBinding {
public CCodeDynamicMethodBinding (CCodeGenerator codegen, DynamicMethod method) {
this.method = method;
this.codegen = codegen;
}
public void generate_wrapper () {
var dynamic_method = (DynamicMethod) method;
var func = new CCodeFunction (method.get_cname (), method.return_type.get_cname ());
var cparam_map = new HashMap<int,CCodeFormalParameter> (direct_hash, direct_equal);
var instance_param = new CCodeFormalParameter ("obj", "gpointer");
cparam_map.set (codegen.get_param_pos (method.cinstance_parameter_position), instance_param);
generate_cparameters (method, method.return_type, cparam_map, func);
var block = new CCodeBlock ();
if (dynamic_method.dynamic_type.data_type == codegen.dbus_object_type) {
generate_dbus_method_wrapper (block);
} else {
Report.error (method.source_reference, "dynamic methods are not supported for `%s'".printf (dynamic_method.dynamic_type.to_string ()));
}
// append to C source file
codegen.source_type_member_declaration.append (func.copy ());
func.block = block;
codegen.source_type_member_definition.append (func);
}
void generate_dbus_method_wrapper (CCodeBlock block) {
var dynamic_method = (DynamicMethod) method;
var expr = dynamic_method.invocation;
var ccall = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_begin_call"));
ccall.add_argument (new CCodeIdentifier ("obj"));
bool found_out = false;
Expression callback = null;
int callback_index = -1;
int arg_index = 1;
foreach (Expression arg in expr.get_argument_list ()) {
if (arg.symbol_reference is Method) {
// callback
if (callback != null) {
Report.error (expr.source_reference, "only one reply callback may be specified in invocation of DBus method");
expr.error = true;
return;
} else if (found_out) {
Report.error (expr.source_reference, "out argument and reply callback conflict in invocation of DBus method");
expr.error = true;
return;
}
callback = arg;
callback_index = arg_index;
} else if (arg is UnaryExpression && ((UnaryExpression) arg).operator == UnaryOperator.OUT) {
// out arg
if (callback != null) {
Report.error (expr.source_reference, "out argument and reply callback conflict in invocation of DBus method");
expr.error = true;
return;
}
found_out = true;
} else {
// in arg
if (callback != null || found_out) {
Report.error (expr.source_reference, "in argument must not follow out argument or reply callback in invocation of DBus method");
expr.error = true;
return;
}
}
arg_index++;
}
ccall.add_argument (new CCodeConstant ("\"%s\"".printf (method.name)));
if (callback != null) {
var reply_method = (Method) callback.symbol_reference;
var cb_fun = new CCodeFunction ("_%s_cb".printf (reply_method.get_cname ()), "void");
cb_fun.modifiers = CCodeModifiers.STATIC;
cb_fun.add_parameter (new CCodeFormalParameter ("proxy", "DBusGProxy*"));
cb_fun.add_parameter (new CCodeFormalParameter ("call", "DBusGProxyCall*"));
cb_fun.add_parameter (new CCodeFormalParameter ("user_data", "void*"));
cb_fun.block = new CCodeBlock ();
var cerrdecl = new CCodeDeclaration ("GError*");
cerrdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("error", new CCodeConstant ("NULL")));
cb_fun.block.add_statement (cerrdecl);
var cend_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_end_call"));
cend_call.add_argument (new CCodeIdentifier ("proxy"));
cend_call.add_argument (new CCodeIdentifier ("call"));
cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("error")));
var creply_call = new CCodeFunctionCall ((CCodeExpression) callback.ccodenode);
creply_call.add_argument (new CCodeIdentifier ("user_data"));
int param_count = reply_method.get_parameters ().size;
int i = 0;
foreach (FormalParameter param in reply_method.get_parameters ()) {
if ((++i) == param_count) {
// error parameter
break;
}
if (param.type_reference is ArrayType && ((ArrayType) param.type_reference).element_type.data_type != codegen.string_type.data_type) {
var array_type = (ArrayType) param.type_reference;
var cdecl = new CCodeDeclaration ("GArray*");
cdecl.add_declarator (new CCodeVariableDeclarator (param.name));
cb_fun.block.add_statement (cdecl);
cend_call.add_argument (get_dbus_array_type (array_type));
cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
creply_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), "data"));
creply_call.add_argument (new CCodeMemberAccess.pointer (new CCodeIdentifier (param.name), "len"));
} else {
var cdecl = new CCodeDeclaration (param.type_reference.get_cname ());
cdecl.add_declarator (new CCodeVariableDeclarator (param.name));
cb_fun.block.add_statement (cdecl);
if (param.type_reference is ArrayType && ((ArrayType) param.type_reference).element_type.data_type == codegen.string_type.data_type) {
// special case string array
cend_call.add_argument (new CCodeIdentifier ("G_TYPE_STRV"));
var cstrvlen = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length"));
cstrvlen.add_argument (new CCodeIdentifier (param.name));
creply_call.add_argument (cstrvlen);
} else {
cend_call.add_argument (new CCodeIdentifier (param.type_reference.data_type.get_type_id ()));
}
cend_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (param.name)));
creply_call.add_argument (new CCodeIdentifier (param.name));
}
}
cend_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
cb_fun.block.add_statement (new CCodeExpressionStatement (cend_call));
creply_call.add_argument (new CCodeIdentifier ("error"));
cb_fun.block.add_statement (new CCodeExpressionStatement (creply_call));
codegen.source_type_member_definition.append (cb_fun);
ccall.add_argument (new CCodeIdentifier (cb_fun.name));
ccall.add_argument (new CCodeConstant ("param%d_target".printf (callback_index)));
ccall.add_argument (new CCodeConstant ("NULL"));
} else if (found_out || !(method.return_type is VoidType)) {
ccall.call = new CCodeIdentifier ("dbus_g_proxy_call");
ccall.add_argument (new CCodeIdentifier ("error"));
} else {
ccall.call = new CCodeIdentifier ("dbus_g_proxy_call_no_reply");
}
foreach (FormalParameter param in method.get_parameters ()) {
if (param.type_reference is MethodType) {
// callback parameter
break;
}
ccall.add_argument (new CCodeIdentifier (param.type_reference.data_type.get_type_id ()));
ccall.add_argument (new CCodeIdentifier (param.name));
}
ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
if (!(method.return_type is VoidType)) {
// synchronous D-Bus method call with reply
var array_type = method.return_type as ArrayType;
if (array_type != null && array_type.element_type.data_type != codegen.string_type.data_type) {
// non-string arrays (use GArray)
ccall.add_argument (get_dbus_array_type (array_type));
var garray_type_reference = codegen.get_data_type_for_symbol (codegen.garray_type);
var cdecl = new CCodeDeclaration (garray_type_reference.get_cname ());
cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
block.add_statement (cdecl);
ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
block.add_statement (new CCodeExpressionStatement (ccall));
block.add_statement (new CCodeReturnStatement (new CCodeMemberAccess.pointer (new CCodeIdentifier ("result"), "data")));
if (!method.no_array_length) {
expr.append_array_size (new CCodeMemberAccess.pointer (new CCodeIdentifier ("result"), "len"));
} else {
expr.append_array_size (new CCodeConstant ("-1"));
}
} else {
// string arrays or other datatypes
if (method.return_type is ArrayType) {
// string arrays
ccall.add_argument (new CCodeIdentifier ("G_TYPE_STRV"));
} else {
// other types
ccall.add_argument (new CCodeIdentifier (method.return_type.data_type.get_type_id ()));
}
var cdecl = new CCodeDeclaration (method.return_type.get_cname ());
cdecl.add_declarator (new CCodeVariableDeclarator ("result"));
block.add_statement (cdecl);
ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier ("result")));
ccall.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
block.add_statement (new CCodeExpressionStatement (ccall));
block.add_statement (new CCodeReturnStatement (new CCodeIdentifier ("result")));
if (array_type != null) {
// special case string array
if (!method.no_array_length) {
var cstrvlen = new CCodeFunctionCall (new CCodeIdentifier ("g_strv_length"));
cstrvlen.add_argument (new CCodeIdentifier ("result"));
expr.append_array_size (cstrvlen);
} else {
expr.append_array_size (new CCodeConstant ("-1"));
}
}
}
} else {
block.add_statement (new CCodeExpressionStatement (ccall));
}
}
CCodeExpression get_dbus_array_type (ArrayType array_type) {
var carray_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_collection"));
carray_type.add_argument (new CCodeConstant ("\"GArray\""));
carray_type.add_argument (new CCodeIdentifier (array_type.element_type.data_type.get_type_id ()));
return carray_type;
}
}
/* valaccodedynamicsignalbinding.vala
*
* Copyright (C) 2007-2008 Jürg Billeter
*
* 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:
* Jürg Billeter <j@bitron.ch>
*/
using GLib;
using Gee;
/**
* The link between a dynamic signal and generated code.
*/
public class Vala.CCodeDynamicSignalBinding : CCodeBinding {
public Signal node { get; set; }
public CCodeDynamicSignalBinding (CCodeGenerator codegen, DynamicSignal node) {
this.node = node;
this.codegen = codegen;
}
string? connect_wrapper_name;
string? disconnect_wrapper_name;
public string get_connect_wrapper_name () {
var dynamic_signal = (DynamicSignal) node;
if (connect_wrapper_name == null) {
connect_wrapper_name = "_dynamic_%s_connect".printf (node.name);
var func = new CCodeFunction (connect_wrapper_name, "void");
func.add_parameter (new CCodeFormalParameter ("obj", "gpointer"));
func.add_parameter (new CCodeFormalParameter ("signal_name", "const char *"));
func.add_parameter (new CCodeFormalParameter ("handler", "GCallback"));
func.add_parameter (new CCodeFormalParameter ("data", "gpointer"));
var block = new CCodeBlock ();
if (dynamic_signal.dynamic_type.data_type == codegen.dbus_object_type) {
generate_dbus_connect_wrapper (block);
} else {
Report.error (node.source_reference, "dynamic signals are not supported for `%s'".printf (dynamic_signal.dynamic_type.to_string ()));
}
// append to C source file
codegen.source_type_member_declaration.append (func.copy ());
func.block = block;
codegen.source_type_member_definition.append (func);
}
return connect_wrapper_name;
}
public string get_disconnect_wrapper_name () {
var dynamic_signal = (DynamicSignal) node;
if (disconnect_wrapper_name == null) {
disconnect_wrapper_name = "_dynamic_%s_disconnect".printf (node.name);
var func = new CCodeFunction (disconnect_wrapper_name, "void");
func.add_parameter (new CCodeFormalParameter ("obj", "gpointer"));
func.add_parameter (new CCodeFormalParameter ("signal_name", "const char *"));
func.add_parameter (new CCodeFormalParameter ("handler", "GCallback"));
func.add_parameter (new CCodeFormalParameter ("data", "gpointer"));
var block = new CCodeBlock ();
if (dynamic_signal.dynamic_type.data_type == codegen.dbus_object_type) {
generate_dbus_disconnect_wrapper (block);
} else {
Report.error (node.source_reference, "dynamic signals are not supported for `%s'".printf (dynamic_signal.dynamic_type.to_string ()));
}
// append to C source file
codegen.source_type_member_declaration.append (func.copy ());
func.block = block;
codegen.source_type_member_definition.append (func);
}
return disconnect_wrapper_name;
}
void generate_dbus_connect_wrapper (CCodeBlock block) {
var dynamic_signal = (DynamicSignal) node;
var m = (Method) dynamic_signal.handler.symbol_reference;
bool first = true;
foreach (FormalParameter param in m.get_parameters ()) {
if (first) {
// skip sender parameter
first = false;
continue;
}
node.add_parameter (param.copy ());
}
node.accept (codegen);
// FIXME should only be done once per marshaller
var register_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_object_register_marshaller"));
register_call.add_argument (new CCodeIdentifier (codegen.get_signal_marshaller_function (node)));
register_call.add_argument (new CCodeIdentifier ("G_TYPE_NONE"));
var add_call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_add_signal"));
add_call.add_argument (new CCodeIdentifier ("obj"));
add_call.add_argument (new CCodeConstant ("\"%s\"".printf (node.name)));
first = true;
foreach (FormalParameter param in m.get_parameters ()) {
if (first) {
// skip sender parameter
first = false;
continue;
}
if (param.type_reference is ArrayType && ((ArrayType) param.type_reference).element_type.data_type != codegen.string_type.data_type) {
var array_type = (ArrayType) param.type_reference;
if (array_type.element_type.data_type.get_type_id () == null) {
Report.error (param.source_reference, "unsupported parameter type for D-Bus signals");
return;
}
var carray_type = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_type_get_collection"));
carray_type.add_argument (new CCodeConstant ("\"GArray\""));
carray_type.add_argument (new CCodeIdentifier (array_type.element_type.data_type.get_type_id ()));
register_call.add_argument (carray_type);
add_call.add_argument (carray_type);
} else {
if (param.type_reference.get_type_id () == null) {
Report.error (param.source_reference, "unsupported parameter type for D-Bus signals");
return;
}
register_call.add_argument (new CCodeIdentifier (param.type_reference.get_type_id ()));
add_call.add_argument (new CCodeIdentifier (param.type_reference.get_type_id ()));
}
}
register_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
add_call.add_argument (new CCodeIdentifier ("G_TYPE_INVALID"));
block.add_statement (new CCodeExpressionStatement (register_call));
block.add_statement (new CCodeExpressionStatement (add_call));
var call = new CCodeFunctionCall (new CCodeIdentifier ("dbus_g_proxy_connect_signal"));
call.add_argument (new CCodeIdentifier ("obj"));
call.add_argument (new CCodeIdentifier ("signal_name"));
call.add_argument (new CCodeIdentifier ("handler"));
call.add_argument (new CCodeIdentifier ("data"));
call.add_argument (new CCodeConstant ("NULL"));
block.add_statement (new CCodeExpressionStatement (call));
}
void generate_dbus_disconnect_wrapper