void generate_marshaller(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); 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"); signal_marshaller.modifiers = CCodeModifiers.STATIC; signal_marshaller.add_parameter(new CCodeParameter("closure", "GClosure *")); signal_marshaller.add_parameter(new CCodeParameter("return_value", "GValue *")); signal_marshaller.add_parameter(new CCodeParameter("n_param_values", "guint")); signal_marshaller.add_parameter(new CCodeParameter("param_values", "const GValue *")); signal_marshaller.add_parameter(new CCodeParameter("invocation_hint", "gpointer")); signal_marshaller.add_parameter(new CCodeParameter("marshal_data", "gpointer")); push_function(signal_marshaller); var callback_decl = new CCodeFunctionDeclarator(get_marshaller_function(_params, return_type, "GMarshalFunc")); callback_decl.add_parameter(new CCodeParameter("data1", "gpointer")); n_params = 1; foreach (Parameter p in _params) { callback_decl.add_parameter(new CCodeParameter("arg_%d".printf(n_params), get_value_type_name_from_parameter(p))); n_params++; if (p.variable_type.is_array()) { for (var j = 0; j < ((ArrayType)p.variable_type).rank; j++) { callback_decl.add_parameter(new CCodeParameter("arg_%d".printf(n_params), "gint")); 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("GCClosure *", new CCodeVariableDeclarator("cc", new CCodeCastExpression(new CCodeIdentifier("closure"), "GCClosure *")), CCodeModifiers.REGISTER); ccode.add_declaration("gpointer", new CCodeVariableDeclarator("data1"), CCodeModifiers.REGISTER); ccode.add_declaration("gpointer", new CCodeVariableDeclarator("data2"), CCodeModifiers.REGISTER); CCodeFunctionCall fc; if (return_type.data_type != null || return_type.is_array()) { ccode.add_declaration(get_value_type_name_from_type_reference(return_type), new CCodeVariableDeclarator("v_return")); fc = new CCodeFunctionCall(new CCodeIdentifier("g_return_if_fail")); fc.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.INEQUALITY, new CCodeIdentifier("return_value"), new CCodeConstant("NULL"))); ccode.add_expression(fc); } fc = new CCodeFunctionCall(new CCodeIdentifier("g_return_if_fail")); fc.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.EQUALITY, new CCodeIdentifier("n_param_values"), new CCodeConstant(n_params.ToString()))); ccode.add_expression(fc); var data = new CCodeMemberAccess(new CCodeIdentifier("closure"), "data", true); var param = new CCodeMemberAccess(new CCodeMemberAccess(new CCodeIdentifier("param_values"), "data[0]", true), "v_pointer"); var cond = new CCodeFunctionCall(new CCodeConstant("G_CCLOSURE_SWAP_DATA")); cond.add_argument(new CCodeIdentifier("closure")); ccode.open_if(cond); ccode.add_assignment(new CCodeIdentifier("data1"), data); ccode.add_assignment(new CCodeIdentifier("data2"), param); ccode.add_else(); ccode.add_assignment(new CCodeIdentifier("data1"), param); 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")); ccode.add_assignment(new CCodeIdentifier("callback"), c_assign_rhs); fc = new CCodeFunctionCall(new CCodeIdentifier("callback")); fc.add_argument(new CCodeIdentifier("data1")); i = 1; foreach (Parameter p in _params) { string get_value_function; bool is_array = p.variable_type.is_array(); if (p.direction != ParameterDirection.IN) { get_value_function = "g_value_get_pointer"; } else if (is_array) { if (((ArrayType)p.variable_type).element_type.data_type == string_type.data_type) { get_value_function = "g_value_get_boxed"; } else { get_value_function = "g_value_get_pointer"; } } else if (p.variable_type is PointerType || p.variable_type.type_parameter != null) { get_value_function = "g_value_get_pointer"; } else if (p.variable_type is ErrorType) { get_value_function = "g_value_get_pointer"; } else if (p.variable_type is ValaValueType && p.variable_type.nullable) { get_value_function = "g_value_get_pointer"; } else { get_value_function = get_ccode_get_value_function(p.variable_type.data_type); } var inner_fc = new CCodeFunctionCall(new CCodeIdentifier(get_value_function)); inner_fc.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, new CCodeIdentifier("param_values"), new CCodeIdentifier(i.ToString()))); fc.add_argument(inner_fc); i++; if (is_array) { for (var j = 0; j < ((ArrayType)p.variable_type).rank; j++) { inner_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_get_int")); inner_fc.add_argument(new CCodeBinaryExpression(CCodeBinaryOperator.PLUS, new CCodeIdentifier("param_values"), new CCodeIdentifier(i.ToString()))); fc.add_argument(inner_fc); i++; } } } fc.add_argument(new CCodeIdentifier("data2")); if (return_type.data_type != null || return_type.is_array()) { ccode.add_assignment(new CCodeIdentifier("v_return"), fc); CCodeFunctionCall set_fc; if (return_type.is_array()) { if (((ArrayType)return_type).element_type.data_type == string_type.data_type) { set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_take_boxed")); } else { set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_set_pointer")); } } else if (return_type.type_parameter != null) { set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_set_pointer")); } else if (return_type is ErrorType) { set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_set_pointer")); } else if (return_type.data_type == string_type.data_type) { set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_take_string")); } else if (return_type.data_type is Class || return_type.data_type is Interface) { set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_take_object")); } else if (return_type is ValaValueType && return_type.nullable) { set_fc = new CCodeFunctionCall(new CCodeIdentifier("g_value_set_pointer")); } else { set_fc = new CCodeFunctionCall(new CCodeIdentifier(get_ccode_set_value_function(return_type.data_type))); } set_fc.add_argument(new CCodeIdentifier("return_value")); set_fc.add_argument(new CCodeIdentifier("v_return")); ccode.add_expression(set_fc); } else { ccode.add_expression(fc); } pop_function(); cfile.add_function_declaration(signal_marshaller); cfile.add_function(signal_marshaller); user_marshal_set.Add(signature); }
public override void generate_delegate_declaration(ValaDelegate d, CCodeFile decl_space) { if (add_symbol_declaration(decl_space, d, get_ccode_name(d))) { return; } string return_type_cname = get_ccode_name(d.return_type); if (d.return_type.is_real_non_null_struct_type()) { // structs are returned via out parameter return_type_cname = "void"; } if (return_type_cname == get_ccode_name(d)) { // recursive delegate return_type_cname = "GCallback"; } else { generate_type_declaration(d.return_type, decl_space); } var cfundecl = new CCodeFunctionDeclarator(get_ccode_name(d)); foreach (Parameter param in d.get_parameters()) { var cparam = generate_parameter(param, decl_space, new Dictionary <int, CCodeParameter>(), null); cfundecl.add_parameter(cparam); // handle array parameters if (get_ccode_array_length(param) && param.variable_type is ArrayType) { var array_type = (ArrayType)param.variable_type; var length_ctype = "int"; if (param.direction != ParameterDirection.IN) { length_ctype = "int*"; } for (int dim = 1; dim <= array_type.rank; dim++) { cparam = new CCodeParameter(get_parameter_array_length_cname(param, dim), length_ctype); cfundecl.add_parameter(cparam); } } // handle delegate parameters if (param.variable_type is DelegateType) { var deleg_type = (DelegateType)param.variable_type; var param_d = deleg_type.delegate_symbol; if (param_d.has_target) { cparam = new CCodeParameter(get_delegate_target_cname(get_variable_cname(param.name)), "void*"); cfundecl.add_parameter(cparam); if (deleg_type.is_disposable()) { cparam = new CCodeParameter(get_delegate_target_destroy_notify_cname(get_variable_cname(param.name)), "GDestroyNotify*"); cfundecl.add_parameter(cparam); } } } } if (get_ccode_array_length(d) && d.return_type is ArrayType) { // return array length if appropriate var array_type = (ArrayType)d.return_type; var array_length_type = get_ccode_array_length_type(d) != null?get_ccode_array_length_type(d) : "int"; array_length_type += "*"; for (int dim = 1; dim <= array_type.rank; dim++) { var cparam = new CCodeParameter(get_array_length_cname("result", dim), array_length_type); cfundecl.add_parameter(cparam); } } else if (d.return_type is DelegateType) { // return delegate target if appropriate var deleg_type = (DelegateType)d.return_type; var result_d = deleg_type.delegate_symbol; if (result_d.has_target) { var cparam = new CCodeParameter(get_delegate_target_cname("result"), "void**"); cfundecl.add_parameter(cparam); if (deleg_type.is_disposable()) { cparam = new CCodeParameter(get_delegate_target_destroy_notify_cname("result"), "GDestroyNotify*"); cfundecl.add_parameter(cparam); } } } else if (d.return_type.is_real_non_null_struct_type()) { var cparam = new CCodeParameter("result", "%s*".printf(get_ccode_name(d.return_type))); cfundecl.add_parameter(cparam); } if (d.has_target) { var cparam = new CCodeParameter("user_data", "void*"); cfundecl.add_parameter(cparam); } if (d.get_error_types().Count > 0) { var cparam = new CCodeParameter("error", "GError**"); cfundecl.add_parameter(cparam); } var ctypedef = new CCodeTypeDefinition(return_type_cname, cfundecl); ctypedef.modifiers |= (d.version.deprecated ? CCodeModifiers.DEPRECATED : 0); decl_space.add_type_definition(ctypedef); }