Commit f0615f34 authored by Jürg Billeter's avatar Jürg Billeter

Support GVariant casts and GDBus clients and servers

parent 142ca8fe
......@@ -47,12 +47,16 @@ libvala_la_VALASOURCES = \
valadovastructmodule.vala \
valadovavaluemodule.vala \
valaenumregisterfunction.vala \
valagasyncmodule.vala \
valagdbusclientmodule.vala \
valagdbusmodule.vala \
valagdbusservermodule.vala \
valagerrormodule.vala \
valagirwriter.vala \
valagobjectmodule.vala \
valagsignalmodule.vala \
valagtypemodule.vala \
valagasyncmodule.vala \
valagvariantmodule.vala \
valainterfaceregisterfunction.vala \
valastructregisterfunction.vala \
valatyperegisterfunction.vala \
......
......@@ -196,8 +196,10 @@ public class Vala.CCodeBaseModule : CCodeModule {
public DataType gquark_type;
public DataType genumvalue_type;
public Struct gvalue_type;
public Class gvariant_type;
public Struct mutex_type;
public TypeSymbol type_module_type;
public TypeSymbol dbus_proxy_type;
public TypeSymbol dbus_object_type;
public bool in_plugin = false;
......@@ -336,6 +338,7 @@ public class Vala.CCodeBaseModule : CCodeModule {
gquark_type = new IntegerType ((Struct) glib_ns.scope.lookup ("Quark"));
genumvalue_type = new ObjectType ((Class) glib_ns.scope.lookup ("EnumValue"));
gvalue_type = (Struct) glib_ns.scope.lookup ("Value");
gvariant_type = (Class) glib_ns.scope.lookup ("Variant");
mutex_type = (Struct) glib_ns.scope.lookup ("StaticRecMutex");
type_module_type = (TypeSymbol) glib_ns.scope.lookup ("TypeModule");
......@@ -355,6 +358,8 @@ public class Vala.CCodeBaseModule : CCodeModule {
}
}
dbus_proxy_type = (TypeSymbol) glib_ns.scope.lookup ("DBusProxy");
var dbus_ns = root_symbol.scope.lookup ("DBus");
if (dbus_ns != null) {
dbus_object_type = (TypeSymbol) dbus_ns.scope.lookup ("Object");
......@@ -4428,6 +4433,66 @@ public class Vala.CCodeBaseModule : CCodeModule {
return rv;
}
int next_variant_function_id = 0;
public CCodeExpression? try_cast_variant_to_type (CCodeExpression ccodeexpr, DataType from, DataType to, Expression? expr = null) {
if (from == null || gvariant_type == null || from.data_type != gvariant_type) {
return null;
}
string variant_func = "_variant_get%d".printf (++next_variant_function_id);
var ccall = new CCodeFunctionCall (new CCodeIdentifier (variant_func));
ccall.add_argument (ccodeexpr);
var cfunc = new CCodeFunction (variant_func);
cfunc.modifiers = CCodeModifiers.STATIC;
cfunc.add_parameter (new CCodeFormalParameter ("value", "GVariant*"));
if (!to.is_real_non_null_struct_type ()) {
cfunc.return_type = to.get_cname ();
}
if (to.is_real_non_null_struct_type ()) {
// structs are returned via out parameter
cfunc.add_parameter (new CCodeFormalParameter ("result", to.get_cname () + "*"));
} else if (to is ArrayType) {
// return array length if appropriate
var array_type = (ArrayType) to;
for (int dim = 1; dim <= array_type.rank; dim++) {
var temp_decl = get_temp_variable (int_type, false, expr);
temp_vars.add (temp_decl);
ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_decl.name)));
cfunc.add_parameter (new CCodeFormalParameter (head.get_array_length_cname ("result", dim), "int*"));
expr.append_array_size (new CCodeIdentifier (temp_decl.name));
}
}
var block = new CCodeBlock ();
var fragment = new CCodeFragment ();
var result = deserialize_expression (fragment, to, new CCodeIdentifier ("value"), new CCodeIdentifier ("*result"));
block.add_statement (fragment);
block.add_statement (new CCodeReturnStatement (result));
source_declarations.add_type_member_declaration (cfunc.copy ());
cfunc.block = block;
source_type_member_definition.append (cfunc);
return ccall;
}
public virtual CCodeExpression? deserialize_expression (CCodeFragment fragment, DataType type, CCodeExpression variant_expr, CCodeExpression? expr) {
return null;
}
public virtual CCodeExpression? serialize_expression (CCodeFragment fragment, DataType type, CCodeExpression expr) {
return null;
}
public override void visit_cast_expression (CastExpression expr) {
var valuecast = try_cast_value_to_type ((CCodeExpression) expr.inner.ccodenode, expr.inner.value_type, expr.type_reference, expr);
if (valuecast != null) {
......@@ -4435,6 +4500,12 @@ public class Vala.CCodeBaseModule : CCodeModule {
return;
}
var variantcast = try_cast_variant_to_type ((CCodeExpression) expr.inner.ccodenode, expr.inner.value_type, expr.type_reference, expr);
if (variantcast != null) {
expr.ccodenode = variantcast;
return;
}
generate_type_declaration (expr.type_reference, source_declarations);
var cl = expr.type_reference.data_type as Class;
......@@ -4908,6 +4979,10 @@ public class Vala.CCodeBaseModule : CCodeModule {
&& target_type.data_type == gvalue_type
&& !(expression_type is NullType)
&& expression_type.get_type_id () != "G_TYPE_VALUE");
bool gvariant_boxing = (context.profile == Profile.GOBJECT
&& target_type != null
&& target_type.data_type == gvariant_type
&& expression_type.data_type != gvariant_type);
if (expression_type.value_owned
&& (target_type == null || !target_type.value_owned || boxing || unboxing)) {
......@@ -5002,6 +5077,44 @@ public class Vala.CCodeBaseModule : CCodeModule {
cexpr = ccomma;
return cexpr;
} else if (gvariant_boxing) {
// implicit conversion to GVariant
string variant_func = "_variant_new%d".printf (++next_variant_function_id);
var ccall = new CCodeFunctionCall (new CCodeIdentifier (variant_func));
ccall.add_argument (cexpr);
var cfunc = new CCodeFunction (variant_func, "GVariant*");
cfunc.modifiers = CCodeModifiers.STATIC;
cfunc.add_parameter (new CCodeFormalParameter ("value", expression_type.get_cname ()));
if (expression_type is ArrayType) {
// return array length if appropriate
var array_type = (ArrayType) expression_type;
for (int dim = 1; dim <= array_type.rank; dim++) {
ccall.add_argument (head.get_array_length_cexpression (expr, dim));
cfunc.add_parameter (new CCodeFormalParameter (head.get_array_length_cname ("value", dim), "gint"));
}
}
var block = new CCodeBlock ();
var fragment = new CCodeFragment ();
var result = serialize_expression (fragment, expression_type, new CCodeIdentifier ("value"));
// sink floating reference
var sink = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_ref_sink"));
sink.add_argument (result);
block.add_statement (fragment);
block.add_statement (new CCodeReturnStatement (sink));
source_declarations.add_type_member_declaration (cfunc.copy ());
cfunc.block = block;
source_type_member_definition.append (cfunc);
return ccall;
} else if (boxing) {
// value needs to be boxed
......
/* valaccodegenerator.vala
*
* Copyright (C) 2006-2009 Jürg Billeter
* Copyright (C) 2006-2010 Jürg Billeter
* Copyright (C) 2006-2008 Raffaele Sandrini
*
* This library is free software; you can redistribute it and/or
......@@ -50,9 +50,20 @@ public class Vala.CCodeGenerator : CodeGenerator {
head = new GObjectModule (this, head);
head = new GSignalModule (this, head);
head = new GAsyncModule (this, head);
head = new DBusClientModule (this, head);
*/
head = new DBusServerModule (this, head);
if (context.has_package ("dbus-glib-1")) {
/*
head = new DBusModule (this, head);
head = new DBusClientModule (this, head);
*/
head = new DBusServerModule (this, head);
} else {
/*
head = new GVariantModule (this, head);
head = new GDBusClientModule (this, head);
*/
head = new GDBusServerModule (this, head);
}
} else if (context.profile == Profile.DOVA) {
/* included by inheritance
head = new DovaBaseModule (this, head);
......
This diff is collapsed.
/* valagdbusmodule.vala
*
* Copyright (C) 2010 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>
*/
public class Vala.GDBusModule : GVariantModule {
public GDBusModule (CCodeGenerator codegen, CCodeModule? next) {
base (codegen, next);
}
public static string? get_dbus_name (TypeSymbol symbol) {
var dbus = symbol.get_attribute ("DBus");
if (dbus == null) {
return null;
}
return dbus.get_string ("name");
}
public static string get_dbus_name_for_member (Symbol symbol) {
var dbus = symbol.get_attribute ("DBus");
if (dbus != null && dbus.has_argument ("name")) {
return dbus.get_string ("name");
}
return Symbol.lower_case_to_camel_case (symbol.name);
}
public override void visit_error_domain (ErrorDomain edomain) {
var edomain_dbus_name = get_dbus_name (edomain);
if (edomain_dbus_name == null) {
base.visit_error_domain (edomain);
return;
}
generate_error_domain_declaration (edomain, source_declarations);
if (!edomain.is_internal_symbol ()) {
generate_error_domain_declaration (edomain, header_declarations);
}
if (!edomain.is_private_symbol ()) {
generate_error_domain_declaration (edomain, internal_header_declarations);
}
var error_entries = new CCodeInitializerList ();
foreach (ErrorCode ecode in edomain.get_codes ()) {
var ecode_dbus_name = get_dbus_name (ecode);
if (ecode_dbus_name == null) {
ecode_dbus_name = Symbol.lower_case_to_camel_case (ecode.name.down ());
}
var error_entry = new CCodeInitializerList ();
error_entry.append (new CCodeIdentifier (ecode.get_cname ()));
error_entry.append (new CCodeConstant ("\"%s\"".printf (ecode_dbus_name)));
error_entries.append (error_entry);
}
var cdecl = new CCodeDeclaration ("const GDBusErrorEntry");
cdecl.add_declarator (new CCodeVariableDeclarator (edomain.get_lower_case_cname () + "_entries[]", error_entries));
cdecl.modifiers = CCodeModifiers.STATIC;
source_declarations.add_constant_declaration (cdecl);
string quark_fun_name = edomain.get_lower_case_cprefix () + "quark";
var cquark_fun = new CCodeFunction (quark_fun_name, gquark_type.data_type.get_cname ());
var cquark_block = new CCodeBlock ();
string quark_name = "%squark_volatile".printf (edomain.get_lower_case_cprefix ());
cdecl = new CCodeDeclaration ("gsize");
cdecl.add_declarator (new CCodeVariableDeclarator (quark_name, new CCodeConstant ("0")));
cdecl.modifiers = CCodeModifiers.STATIC | CCodeModifiers.VOLATILE;
cquark_block.add_statement (cdecl);
var register_call = new CCodeFunctionCall (new CCodeIdentifier ("g_dbus_error_register_error_domain"));
register_call.add_argument (new CCodeConstant ("\"" + edomain.get_lower_case_cname () + "-quark\""));
register_call.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (quark_name)));
register_call.add_argument (new CCodeIdentifier (edomain.get_lower_case_cname () + "_entries"));
var nentries = new CCodeFunctionCall (new CCodeIdentifier ("G_N_ELEMENTS"));
nentries.add_argument (new CCodeIdentifier (edomain.get_lower_case_cname () + "_entries"));
register_call.add_argument (nentries);
cquark_block.add_statement (new CCodeExpressionStatement (register_call));
cquark_block.add_statement (new CCodeReturnStatement (new CCodeCastExpression (new CCodeIdentifier (quark_name), "GQuark")));
cquark_fun.block = cquark_block;
source_type_member_definition.append (cquark_fun);
}
public override CCodeFragment register_dbus_info (ObjectTypeSymbol sym) {
return new CCodeFragment ();
}
}
This diff is collapsed.
This diff is collapsed.
......@@ -186,6 +186,11 @@ public class Vala.ArrayType : ReferenceType {
return true;
}
if (target_type.get_type_id () == "G_TYPE_VARIANT") {
// allow implicit conversion to GVariant
return true;
}
if (target_type is PointerType || (target_type.data_type != null && target_type.data_type.get_attribute ("PointerType") != null)) {
/* any array type can be cast to a generic pointer */
return true;
......
/* valadatatype.vala
*
* Copyright (C) 2006-2009 Jürg Billeter
* Copyright (C) 2006-2010 Jürg Billeter
* Copyright (C) 2006-2008 Raffaele Sandrini
*
* This library is free software; you can redistribute it and/or
......@@ -314,6 +314,11 @@ public abstract class Vala.DataType : CodeNode {
return true;
}
if (target_type.get_type_id () == "G_TYPE_VARIANT") {
// allow implicit conversion to GVariant
return true;
}
if (target_type is DelegateType && this is DelegateType) {
return ((DelegateType) target_type).delegate_symbol == ((DelegateType) this).delegate_symbol;
}
......
......@@ -7,6 +7,8 @@ namespace GLib {
[CCode (cheader_filename = "gio/gio.h")]
public static async GLib.DBusConnection @get (GLib.BusType bus_type, GLib.Cancellable? cancellable = null) throws GLib.IOError;
[CCode (cheader_filename = "gio/gio.h")]
public static T get_proxy_sync<T> (GLib.BusType bus_type, string name, string object_path, GLib.Cancellable? cancellable = null) throws GLib.IOError;
[CCode (cheader_filename = "gio/gio.h")]
public static GLib.DBusConnection get_sync (GLib.BusType bus_type, GLib.Cancellable? cancellable = null) throws GLib.IOError;
[CCode (cheader_filename = "gio/gio.h")]
public static uint own_name (GLib.BusType bus_type, string name, GLib.BusNameOwnerFlags flags, GLib.BusAcquiredCallback bus_acquired_handler, GLib.BusNameAcquiredCallback name_acquired_handler, GLib.BusNameLostCallback name_lost_handler);
......@@ -206,7 +208,7 @@ namespace GLib {
public unowned GLib.IOStream get_stream ();
public unowned string get_unique_name ();
public bool is_closed ();
public uint register_object (string object_path, GLib.DBusInterfaceInfo introspection_data, GLib.DBusInterfaceVTable vtable, GLib.DestroyNotify user_data_free_func) throws GLib.Error;
public uint register_object<T> (string object_path, T object) throws GLib.IOError;
public uint register_subtree (string object_path, GLib.DBusSubtreeVTable vtable, GLib.DBusSubtreeFlags flags, GLib.DestroyNotify user_data_free_func) throws GLib.Error;
public void remove_filter (uint filter_id);
public bool send_message (GLib.DBusMessage message, uint32 out_serial) throws GLib.Error;
......
......@@ -56,6 +56,7 @@ namespace GLib {
namespace Bus {
public async GLib.DBusConnection get (GLib.BusType bus_type, GLib.Cancellable? cancellable = null) throws GLib.IOError;
public GLib.DBusConnection get_sync (GLib.BusType bus_type, GLib.Cancellable? cancellable = null) throws GLib.IOError;
public T get_proxy_sync<T> (GLib.BusType bus_type, string name, string object_path, GLib.Cancellable? cancellable = null) throws GLib.IOError;
public uint own_name (GLib.BusType bus_type, string name, GLib.BusNameOwnerFlags flags, GLib.BusAcquiredCallback bus_acquired_handler, GLib.BusNameAcquiredCallback name_acquired_handler, GLib.BusNameLostCallback name_lost_handler);
public uint own_name_on_connection (GLib.DBusConnection connection, string name, GLib.BusNameOwnerFlags flags, GLib.BusNameAcquiredCallback name_acquired_handler, GLib.BusNameLostCallback name_lost_handler);
public uint own_name_on_connection_with_closures (GLib.DBusConnection connection, string name, GLib.BusNameOwnerFlags flags, GLib.Closure name_acquired_closure, GLib.Closure name_lost_closure);
......@@ -67,4 +68,9 @@ namespace GLib {
public uint watch_name_on_connection_with_closures (GLib.DBusConnection connection, string name, GLib.BusNameWatcherFlags flags, GLib.Closure name_appeared_closure, GLib.Closure name_vanished_closure);
public uint watch_name_with_closures (GLib.BusType bus_type, string name, GLib.BusNameWatcherFlags flags, GLib.Closure name_appeared_closure, GLib.Closure name_vanished_closure);
}
[CCode (cname = "GDBusConnection")]
public class DBusConnection {
public uint register_object<T> (string object_path, T object) throws GLib.IOError;
}
}
......@@ -202,3 +202,4 @@ g_zlib_compressor_new.level default_value="-1"
uid_t name="uint"
g_bus_* hidden="1"
g_dbus_connection_register_object hidden="1"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment