mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2025-12-25 09:20:10 +01:00
2005-02-17 Colin Walters <walters@verbum.org>
This patch is based on initial work from Paul Kuliniewicz <kuliniew@purdue.edu>. * glib/dbus-gvalue.c (dbus_gvalue_init): New function; move initialization of GValue from dbus type to here. (dbus_gvalue_genmarshal_name_from_type): New function; generates a string for the "glib-genmarshal" program from a DBus type. (dbus_gvalue_binding_type_from_type): New function; turns a DBus type into the C name for it we use in the glib bindings. (dbus_gvalue_ctype_from_type): New function; maps a DBus type into a glib C type (not GValue). (dbus_gvalue_demarshal): invoke dbus_gvalue_init. * glib/dbus-gutils.c (_dbus_gutils_wincaps_to_uscore): Moved here from dbus-gobject.c. * glib/dbus-gutils.h: Prototype it. * glib/dbus-gproxy.c: Include new dbus-gobject.h. (marshal_dbus_message_to_g_marshaller): Use new shared function dbus_glib_marshal_dbus_message_to_gvalue_array. * glib/dbus-gparser.c (parse_interface, parse_method): Handle c_name attribute. Will be changed once we have annotations. * glib/dbus-gobject.c: Change info_hash_mutex from GStaticMutex to GStaticRWLock. Callers updated. (wincaps_to_uscore): Move to dbus-gutils.c. Callers updated. (string_table_next): New function for iterating over zero-terminated string value array. (string_table_lookup): New function; retrieves specific entry in array. (get_method_data): New function; look up method data in object data chunk. (object_error_domain_prefix_from_object_info) (object_error_code_from_object_info): New functions, but not implemented yet. (method_interface_from_object_info): New function; retrieve interface name. (method_name_from_object_info): New function; retrieve method name. (method_arg_info_from_object_info): New function; retrieve argument data. (arg_iterate): New function; iterates over serialized argument data. (method_dir_signature_from_object_info): New function; returns a GString holding type signature for arguments for just one direction (input or output). (method_input_signature_from_object_info) (method_output_signature_from_object_info): New functions. (dbus_glib_marshal_dbus_message_to_gvalue_array): New shared function; converts dbus message arguments into a GValue array. Used for both signal handling and method invocation. (struct DBusGlibWriteIterfaceData): New utility structure. (write_interface): New function; generate introspection XML for an interface. (introspect_interfaces): New function; gathers all interface->methods, generates introspection XML for them. (handle_introspect): Invoke introspect_interfaces. (get_object_property): Be sure to zero-initalize stack-allocated GValue. (lookup_object_and_method): New function; examines an incoming message and attempts to match it up (via interface, method name, and argument signature) with a known object and method. (gerror_domaincode_to_dbus_error_name): New function; converts a GError domain and code into a DBus error name. Needs GError data added to object introspection to work well. (gerror_to_dbus_error_message): Creates a DBusMessage error return from GError. (invoke_object_method): New function to invoke an object method looked up via lookup_object_and_method. Parses the incoming message, turns it into a GValue array, then invokes the marshaller specified in the DBusGMethodInfo. Creates a new message with either return values or error message as appropriate. (gobject_message_function): Invoke lookup_object_and_method and invoke_object_method. * glib/dbus-glib-tool.c: Include dbus-binding-tool-glib.h. (enum DBusBindingOutputMode): New enum for binding output modes. (pretty_print): Print binding names. (dbus_binding_tool_error_quark): GError bits. (version): Fix typo. (main): Create GIOChannel for output. Parse new --mode argument, possible values are "pretty-print", "glib-server", "glib-client". Use mode to invoke appropriate function. * glib/dbus-gobject.h: Prototype dbus_glib_marshal_dbus_message_to_gvalue_array. * glib/dbus-glib-tool.h: New header, just includes GError bits for now. * glib/dbus-gidl.c (struct InterfaceInfo): Add bindings hashtable; maps binding style to name. (struct MethodInfo): Ditto. (get_hash_keys, get_hash_key): Utility function, returns keys for a GHashTable. (interface_info_new, method_info_new): Initialize bindings. (interface_info_unref, method_info_unref): Destroy bindings. (method_info_get_binding_names, method_info_get_binding_name) (interface_info_get_binding_names, interface_info_get_binding_name): Functions for retrieving binding names. (method_info_set_binding_name, interface_info_set_binding_name): Functions for setting binding names. * glib/dbus-binding-tool-glib.h: New file, has prototypes for glib binding generation. * glib/dbus-binding-tool-glib.c: New file, implements server-side and client-side glib glue generation. * glib/Makefile.am (dbus_binding_tool_SOURCES): Add dbus-binding-tool-glib.c, dbus-binding-tool-glib.h, dbus-glib-tool.h. * dbus/dbus-glib.h (struct DBusGMethodMarshaller): Remove in favor of using GClosureMarshal directly. (struct DBusGObjectInfo): Add n_infos member. * test/glib/test-service-glib.xml: New file; contains introspection data for MyTestObject used in test-service-glib.c. * test/glib/test-service-glib.c (enum MyObjectError): New GError enum. (my_object_do_nothing, my_object_increment, my_object_throw_error) (my_object_uppercase, my_object_many_args): New test methods. (main): Use dbus_g_object_class_install_info to include generated object info. * test/glib/Makefile.am: Generate server-side glue for test-service-glib.c, as well as client-side bindings. * test/glib/test-dbus-glib.c: Include test-service-glib-bindings.h. (main): Activate TestSuiteGLibService; test invoke a bunch of its methods using both the dbus_gproxy stuff directly as well as the generated bindings.
This commit is contained in:
parent
9e4450872a
commit
03f6615eac
21 changed files with 2348 additions and 135 deletions
129
ChangeLog
129
ChangeLog
|
|
@ -1,3 +1,132 @@
|
|||
2005-02-17 Colin Walters <walters@verbum.org>
|
||||
|
||||
This patch is based on initial work from
|
||||
Paul Kuliniewicz <kuliniew@purdue.edu>.
|
||||
|
||||
* glib/dbus-gvalue.c (dbus_gvalue_init): New function; move
|
||||
initialization of GValue from dbus type to here.
|
||||
(dbus_gvalue_genmarshal_name_from_type): New function; generates a string
|
||||
for the "glib-genmarshal" program from a DBus type.
|
||||
(dbus_gvalue_binding_type_from_type): New function; turns a DBus type
|
||||
into the C name for it we use in the glib bindings.
|
||||
(dbus_gvalue_ctype_from_type): New function; maps a DBus type into a
|
||||
glib C type (not GValue).
|
||||
(dbus_gvalue_demarshal): invoke dbus_gvalue_init.
|
||||
|
||||
* glib/dbus-gutils.c (_dbus_gutils_wincaps_to_uscore): Moved here
|
||||
from dbus-gobject.c.
|
||||
|
||||
* glib/dbus-gutils.h: Prototype it.
|
||||
|
||||
* glib/dbus-gproxy.c: Include new dbus-gobject.h.
|
||||
(marshal_dbus_message_to_g_marshaller): Use new shared function
|
||||
dbus_glib_marshal_dbus_message_to_gvalue_array.
|
||||
|
||||
* glib/dbus-gparser.c (parse_interface, parse_method): Handle c_name attribute.
|
||||
Will be changed once we have annotations.
|
||||
|
||||
* glib/dbus-gobject.c: Change info_hash_mutex from GStaticMutex to
|
||||
GStaticRWLock. Callers updated.
|
||||
(wincaps_to_uscore): Move to dbus-gutils.c. Callers updated.
|
||||
(string_table_next): New function for iterating over zero-terminated
|
||||
string value array.
|
||||
(string_table_lookup): New function; retrieves specific entry in
|
||||
array.
|
||||
(get_method_data): New function; look up method data in object data chunk.
|
||||
(object_error_domain_prefix_from_object_info)
|
||||
(object_error_code_from_object_info): New functions, but not implemented yet.
|
||||
(method_interface_from_object_info): New function; retrieve interface name.
|
||||
(method_name_from_object_info): New function; retrieve method name.
|
||||
(method_arg_info_from_object_info): New function; retrieve argument data.
|
||||
(arg_iterate): New function; iterates over serialized argument data.
|
||||
(method_dir_signature_from_object_info): New function; returns a
|
||||
GString holding type signature for arguments for just one
|
||||
direction (input or output).
|
||||
(method_input_signature_from_object_info)
|
||||
(method_output_signature_from_object_info): New functions.
|
||||
(dbus_glib_marshal_dbus_message_to_gvalue_array): New shared function;
|
||||
converts dbus message arguments into a GValue array. Used for both
|
||||
signal handling and method invocation.
|
||||
(struct DBusGlibWriteIterfaceData): New utility structure.
|
||||
(write_interface): New function; generate introspection XML for
|
||||
an interface.
|
||||
(introspect_interfaces): New function; gathers all interface->methods,
|
||||
generates introspection XML for them.
|
||||
(handle_introspect): Invoke introspect_interfaces.
|
||||
(get_object_property): Be sure to zero-initalize stack-allocated GValue.
|
||||
(lookup_object_and_method): New function; examines an incoming message
|
||||
and attempts to match it up (via interface, method name, and argument
|
||||
signature) with a known object and method.
|
||||
(gerror_domaincode_to_dbus_error_name): New function; converts a
|
||||
GError domain and code into a DBus error name. Needs GError data
|
||||
added to object introspection to work well.
|
||||
(gerror_to_dbus_error_message): Creates a DBusMessage error return from
|
||||
GError.
|
||||
(invoke_object_method): New function to invoke an object method
|
||||
looked up via lookup_object_and_method. Parses the incoming
|
||||
message, turns it into a GValue array, then invokes the marshaller
|
||||
specified in the DBusGMethodInfo. Creates a new message with
|
||||
either return values or error message as appropriate.
|
||||
(gobject_message_function): Invoke lookup_object_and_method and
|
||||
invoke_object_method.
|
||||
|
||||
* glib/dbus-glib-tool.c: Include dbus-binding-tool-glib.h.
|
||||
(enum DBusBindingOutputMode): New enum for binding output modes.
|
||||
(pretty_print): Print binding names.
|
||||
(dbus_binding_tool_error_quark): GError bits.
|
||||
(version): Fix typo.
|
||||
(main): Create GIOChannel for output. Parse new --mode argument,
|
||||
possible values are "pretty-print", "glib-server", "glib-client".
|
||||
Use mode to invoke appropriate function.
|
||||
|
||||
* glib/dbus-gobject.h: Prototype dbus_glib_marshal_dbus_message_to_gvalue_array.
|
||||
|
||||
* glib/dbus-glib-tool.h: New header, just includes GError bits
|
||||
for now.
|
||||
|
||||
* glib/dbus-gidl.c (struct InterfaceInfo): Add bindings hashtable;
|
||||
maps binding style to name.
|
||||
(struct MethodInfo): Ditto.
|
||||
(get_hash_keys, get_hash_key): Utility function, returns keys for
|
||||
a GHashTable.
|
||||
(interface_info_new, method_info_new): Initialize bindings.
|
||||
(interface_info_unref, method_info_unref): Destroy bindings.
|
||||
(method_info_get_binding_names, method_info_get_binding_name)
|
||||
(interface_info_get_binding_names, interface_info_get_binding_name):
|
||||
Functions for retrieving binding names.
|
||||
(method_info_set_binding_name, interface_info_set_binding_name):
|
||||
Functions for setting binding names.
|
||||
|
||||
* glib/dbus-binding-tool-glib.h: New file, has prototypes
|
||||
for glib binding generation.
|
||||
|
||||
* glib/dbus-binding-tool-glib.c: New file, implements server-side
|
||||
and client-side glib glue generation.
|
||||
|
||||
* glib/Makefile.am (dbus_binding_tool_SOURCES): Add
|
||||
dbus-binding-tool-glib.c, dbus-binding-tool-glib.h,
|
||||
dbus-glib-tool.h.
|
||||
|
||||
* dbus/dbus-glib.h (struct DBusGMethodMarshaller): Remove in favor
|
||||
of using GClosureMarshal directly.
|
||||
(struct DBusGObjectInfo): Add n_infos member.
|
||||
|
||||
* test/glib/test-service-glib.xml: New file; contains introspection data
|
||||
for MyTestObject used in test-service-glib.c.
|
||||
|
||||
* test/glib/test-service-glib.c (enum MyObjectError): New GError enum.
|
||||
(my_object_do_nothing, my_object_increment, my_object_throw_error)
|
||||
(my_object_uppercase, my_object_many_args): New test methods.
|
||||
(main): Use dbus_g_object_class_install_info to include generated object
|
||||
info.
|
||||
|
||||
* test/glib/Makefile.am: Generate server-side glue for test-service-glib.c,
|
||||
as well as client-side bindings.
|
||||
|
||||
* test/glib/test-dbus-glib.c: Include test-service-glib-bindings.h.
|
||||
(main): Activate TestSuiteGLibService; test invoke a bunch of its methods
|
||||
using both the dbus_gproxy stuff directly as well as the generated bindings.
|
||||
|
||||
2005-02-15 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* dbus/dbus-connection.c (dbus_connection_dispatch): always
|
||||
|
|
|
|||
|
|
@ -89,25 +89,21 @@ DBusGConnection* dbus_g_bus_get (DBusBusType type,
|
|||
typedef struct DBusGObjectInfo DBusGObjectInfo;
|
||||
typedef struct DBusGMethodInfo DBusGMethodInfo;
|
||||
|
||||
typedef DBusHandlerResult (* DBusGMethodMarshaller) (DBusGConnection *connection,
|
||||
DBusGMessage *message,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* Object typically generated by dbus-glib-tool that
|
||||
* Object typically generated by dbus-binding-tool that
|
||||
* stores a mapping from introspection data to a
|
||||
* function pointer for a C method to be invoked.
|
||||
*/
|
||||
struct DBusGMethodInfo
|
||||
{
|
||||
GCallback function; /**< C method to invoke */
|
||||
DBusGMethodMarshaller marshaller; /**< Marshaller to go DBusGMessage to C method */
|
||||
GClosureMarshal marshaller; /**< Marshaller to invoke method */
|
||||
int data_offset; /**< Offset into the introspection data */
|
||||
};
|
||||
|
||||
/**
|
||||
* Introspection data for a GObject, normally autogenerated by
|
||||
* a tool such as dbus-glib-tool.
|
||||
* a tool such as dbus-binding-tool.
|
||||
*/
|
||||
struct DBusGObjectInfo
|
||||
{
|
||||
|
|
@ -115,7 +111,8 @@ struct DBusGObjectInfo
|
|||
* by adding DBusGObjectInfo2, DBusGObjectInfo3, etc.
|
||||
*/
|
||||
const DBusGMethodInfo *infos; /**< Array of method pointers */
|
||||
const unsigned char *data; /**< Introspection data */
|
||||
int n_infos; /**< Length of the infos array */
|
||||
const char *data; /**< Introspection data */
|
||||
};
|
||||
|
||||
void dbus_g_object_class_install_info (GObjectClass *object_class,
|
||||
|
|
@ -174,6 +171,7 @@ void dbus_g_proxy_call_no_reply (DBusGProxy *proxy,
|
|||
const char *method,
|
||||
int first_arg_type,
|
||||
...);
|
||||
|
||||
const char* dbus_g_proxy_get_bus_name (DBusGProxy *proxy);
|
||||
|
||||
#undef DBUS_INSIDE_DBUS_GLIB_H
|
||||
|
|
|
|||
|
|
@ -39,6 +39,9 @@ libdbus_gtool_la_LIBADD = libdbus-glib-1.la
|
|||
bin_PROGRAMS=dbus-binding-tool
|
||||
|
||||
dbus_binding_tool_SOURCES = \
|
||||
dbus-binding-tool-glib.h \
|
||||
dbus-binding-tool-glib.c \
|
||||
dbus-glib-tool.h \
|
||||
dbus-glib-tool.c
|
||||
|
||||
dbus_binding_tool_LDADD= -lexpat libdbus-gtool.la
|
||||
|
|
|
|||
812
glib/dbus-binding-tool-glib.c
Normal file
812
glib/dbus-binding-tool-glib.c
Normal file
|
|
@ -0,0 +1,812 @@
|
|||
/* -*- mode: C; c-file-style: "gnu" -*- */
|
||||
/* dbus-binding-tool-glib.c: Output C glue
|
||||
*
|
||||
* Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
|
||||
*
|
||||
* Licensed under the Academic Free License version 2.1
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "dbus-gidl.h"
|
||||
#include "dbus-gparser.h"
|
||||
#include "dbus-gutils.h"
|
||||
#include "dbus-gvalue.h"
|
||||
#include "dbus-glib-tool.h"
|
||||
#include "dbus-binding-tool-glib.h"
|
||||
#include <glib/gi18n.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define MARSHAL_PREFIX "dbus_glib_marshal"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GIOChannel *channel;
|
||||
|
||||
GError **error;
|
||||
|
||||
GHashTable *generated;
|
||||
} DBusBindingToolCData;
|
||||
|
||||
static gboolean gather_marshallers (BaseInfo *base, DBusBindingToolCData *data, GError **error);
|
||||
static gboolean generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error);
|
||||
static gboolean generate_client_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error);
|
||||
|
||||
static char *
|
||||
compute_marshaller (MethodInfo *method, GError **error)
|
||||
{
|
||||
GSList *elt;
|
||||
GString *ret;
|
||||
gboolean first;
|
||||
|
||||
/* All methods required to return boolean for now;
|
||||
* will be conditional on method info later */
|
||||
ret = g_string_new ("BOOLEAN:");
|
||||
|
||||
first = TRUE;
|
||||
/* Append input arguments */
|
||||
for (elt = method_info_get_args (method); elt; elt = elt->next)
|
||||
{
|
||||
ArgInfo *arg = elt->data;
|
||||
|
||||
if (arg_info_get_direction (arg) == ARG_IN)
|
||||
{
|
||||
const char *marshal_name = dbus_gvalue_genmarshal_name_from_type (arg_info_get_type (arg));
|
||||
if (!marshal_name)
|
||||
{
|
||||
g_set_error (error,
|
||||
DBUS_BINDING_TOOL_ERROR,
|
||||
DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
|
||||
_("Unsupported conversion from D-BUS type %d to glib-genmarshal type"),
|
||||
arg_info_get_type (arg));
|
||||
g_string_free (ret, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
if (!first)
|
||||
g_string_append (ret, ",");
|
||||
else
|
||||
first = FALSE;
|
||||
g_string_append (ret, marshal_name);
|
||||
}
|
||||
}
|
||||
|
||||
/* Append pointer for each out arg storage */
|
||||
for (elt = method_info_get_args (method); elt; elt = elt->next)
|
||||
{
|
||||
ArgInfo *arg = elt->data;
|
||||
|
||||
if (arg_info_get_direction (arg) == ARG_OUT)
|
||||
{
|
||||
if (!first)
|
||||
g_string_append (ret, ",");
|
||||
else
|
||||
first = FALSE;
|
||||
g_string_append (ret, "POINTER");
|
||||
}
|
||||
}
|
||||
|
||||
/* Final GError parameter */
|
||||
if (!first)
|
||||
g_string_append (ret, ",");
|
||||
g_string_append (ret, "POINTER");
|
||||
|
||||
return g_string_free (ret, FALSE);
|
||||
|
||||
}
|
||||
|
||||
static char *
|
||||
compute_marshaller_name (MethodInfo *method, GError **error)
|
||||
{
|
||||
GSList *elt;
|
||||
GString *ret;
|
||||
|
||||
/* All methods required to return boolean for now;
|
||||
* will be conditional on method info later */
|
||||
ret = g_string_new (MARSHAL_PREFIX "_BOOLEAN_");
|
||||
|
||||
/* Append input arguments */
|
||||
for (elt = method_info_get_args (method); elt; elt = elt->next)
|
||||
{
|
||||
ArgInfo *arg = elt->data;
|
||||
|
||||
if (arg_info_get_direction (arg) == ARG_IN)
|
||||
{
|
||||
const char *marshal_name;
|
||||
int type;
|
||||
|
||||
type = arg_info_get_type (arg);
|
||||
marshal_name = dbus_gvalue_genmarshal_name_from_type (type);
|
||||
if (!marshal_name)
|
||||
{
|
||||
g_set_error (error,
|
||||
DBUS_BINDING_TOOL_ERROR,
|
||||
DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
|
||||
_("Unsupported conversion from D-BUS type %d to glib-genmarshal type"),
|
||||
type);
|
||||
g_string_free (ret, TRUE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_string_append (ret, "_");
|
||||
g_string_append (ret, dbus_gvalue_genmarshal_name_from_type (arg_info_get_type (arg)));
|
||||
}
|
||||
}
|
||||
|
||||
/* Append pointer for each out arg storage */
|
||||
for (elt = method_info_get_args (method); elt; elt = elt->next)
|
||||
{
|
||||
ArgInfo *arg = elt->data;
|
||||
|
||||
if (arg_info_get_direction (arg) == ARG_OUT)
|
||||
{
|
||||
g_string_append (ret, "_POINTER");
|
||||
}
|
||||
}
|
||||
|
||||
/* Final GError parameter */
|
||||
g_string_append (ret, "_POINTER");
|
||||
|
||||
return g_string_free (ret, FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gather_marshallers_list (GSList *list, DBusBindingToolCData *data, GError **error)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
tmp = list;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
if (!gather_marshallers (tmp->data, data, error))
|
||||
return FALSE;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gather_marshallers (BaseInfo *base, DBusBindingToolCData *data, GError **error)
|
||||
{
|
||||
if (base_info_get_type (base) == INFO_TYPE_NODE)
|
||||
{
|
||||
if (!gather_marshallers_list (node_info_get_nodes ((NodeInfo *) base),
|
||||
data, error))
|
||||
return FALSE;
|
||||
if (!gather_marshallers_list (node_info_get_interfaces ((NodeInfo *) base),
|
||||
data, error))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
InterfaceInfo *interface;
|
||||
GSList *methods;
|
||||
GSList *tmp;
|
||||
const char *interface_c_name;
|
||||
|
||||
interface = (InterfaceInfo *) base;
|
||||
interface_c_name = interface_info_get_binding_name (interface, "C");
|
||||
if (interface_c_name == NULL)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
methods = interface_info_get_methods (interface);
|
||||
|
||||
/* Generate the necessary marshallers for the methods. */
|
||||
|
||||
for (tmp = methods; tmp != NULL; tmp = g_slist_next (tmp))
|
||||
{
|
||||
MethodInfo *method;
|
||||
char *marshaller_name;
|
||||
|
||||
method = (MethodInfo *) tmp->data;
|
||||
if (method_info_get_binding_name (method, "C") == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
marshaller_name = compute_marshaller (method, error);
|
||||
if (!marshaller_name)
|
||||
return FALSE;
|
||||
|
||||
if (g_hash_table_lookup (data->generated, marshaller_name))
|
||||
{
|
||||
g_free (marshaller_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
g_hash_table_insert (data->generated, marshaller_name, NULL);
|
||||
}
|
||||
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
generate_glue_list (GSList *list, DBusBindingToolCData *data, GError **error)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
tmp = list;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
if (!generate_glue (tmp->data, data, error))
|
||||
return FALSE;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define WRITE_OR_LOSE(x) do { gsize bytes_written; if (!g_io_channel_write_chars (channel, x, -1, &bytes_written, error)) goto io_lose; } while (0)
|
||||
|
||||
static gboolean
|
||||
write_printf_to_iochannel (const char *fmt, GIOChannel *channel, GError **error, ...)
|
||||
{
|
||||
char *str;
|
||||
va_list args;
|
||||
GIOStatus status;
|
||||
gsize written;
|
||||
gboolean ret;
|
||||
|
||||
va_start (args, error);
|
||||
|
||||
str = g_strdup_vprintf (fmt, args);
|
||||
if ((status = g_io_channel_write_chars (channel, str, -1, &written, error)) == G_IO_STATUS_NORMAL)
|
||||
ret = TRUE;
|
||||
else
|
||||
ret = FALSE;
|
||||
|
||||
g_free (str);
|
||||
|
||||
va_end (args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
|
||||
{
|
||||
if (base_info_get_type (base) == INFO_TYPE_NODE)
|
||||
{
|
||||
if (!generate_glue_list (node_info_get_nodes ((NodeInfo *) base),
|
||||
data, error))
|
||||
return FALSE;
|
||||
if (!generate_glue_list (node_info_get_interfaces ((NodeInfo *) base),
|
||||
data, error))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
GIOChannel *channel;
|
||||
InterfaceInfo *interface;
|
||||
GSList *methods;
|
||||
GSList *tmp;
|
||||
gsize i;
|
||||
int count;
|
||||
const char *interface_c_name;
|
||||
GString *object_introspection_data_blob;
|
||||
|
||||
channel = data->channel;
|
||||
|
||||
interface = (InterfaceInfo *) base;
|
||||
interface_c_name = interface_info_get_binding_name (interface, "C");
|
||||
if (interface_c_name == NULL)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
object_introspection_data_blob = g_string_new_len ("", 0);
|
||||
|
||||
methods = interface_info_get_methods (interface);
|
||||
count = 0;
|
||||
|
||||
/* Table of marshalled methods. */
|
||||
|
||||
if (!write_printf_to_iochannel ("static const DBusGMethodInfo dbus_glib_%s_methods[] = {\n", channel, error, interface_info_get_binding_name (interface, "C")))
|
||||
goto io_lose;
|
||||
for (tmp = methods; tmp != NULL; tmp = g_slist_next (tmp))
|
||||
{
|
||||
MethodInfo *method;
|
||||
char *marshaller_name;
|
||||
const char *method_c_name;
|
||||
GSList *args;
|
||||
|
||||
method = (MethodInfo *) tmp->data;
|
||||
method_c_name = method_info_get_binding_name (method, "C");
|
||||
if (method_c_name == NULL)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!write_printf_to_iochannel (" { (GCallback) %s, ", channel, error,
|
||||
method_c_name))
|
||||
goto io_lose;
|
||||
|
||||
marshaller_name = compute_marshaller_name (method, error);
|
||||
if (!marshaller_name)
|
||||
goto io_lose;
|
||||
|
||||
if (!write_printf_to_iochannel ("%s, %d },\n", channel, error,
|
||||
marshaller_name,
|
||||
object_introspection_data_blob->len))
|
||||
{
|
||||
g_free (marshaller_name);
|
||||
goto io_lose;
|
||||
}
|
||||
|
||||
/* Object method data blob format:
|
||||
* <iface>\0<name>\0(<argname>\0<argdirection>\0<argtype>\0)*\0
|
||||
*/
|
||||
|
||||
g_string_append (object_introspection_data_blob, interface_info_get_name (interface));
|
||||
g_string_append_c (object_introspection_data_blob, '\0');
|
||||
|
||||
g_string_append (object_introspection_data_blob, method_info_get_name (method));
|
||||
g_string_append_c (object_introspection_data_blob, '\0');
|
||||
|
||||
for (args = method_info_get_args (method); args; args = args->next)
|
||||
{
|
||||
ArgInfo *arg;
|
||||
char direction;
|
||||
|
||||
arg = args->data;
|
||||
|
||||
g_string_append (object_introspection_data_blob, arg_info_get_name (arg));
|
||||
g_string_append_c (object_introspection_data_blob, '\0');
|
||||
|
||||
switch (arg_info_get_direction (arg))
|
||||
{
|
||||
case ARG_IN:
|
||||
direction = 'I';
|
||||
break;
|
||||
case ARG_OUT:
|
||||
direction = 'O';
|
||||
break;
|
||||
case ARG_INVALID:
|
||||
break;
|
||||
}
|
||||
g_string_append_c (object_introspection_data_blob, direction);
|
||||
g_string_append_c (object_introspection_data_blob, '\0');
|
||||
|
||||
g_string_append_c (object_introspection_data_blob, arg_info_get_type (arg));
|
||||
g_string_append_c (object_introspection_data_blob, '\0');
|
||||
}
|
||||
|
||||
g_string_append_c (object_introspection_data_blob, '\0');
|
||||
|
||||
count++;
|
||||
}
|
||||
WRITE_OR_LOSE ("};\n\n");
|
||||
|
||||
/* Information about the object. */
|
||||
|
||||
if (!write_printf_to_iochannel ("const DBusGObjectInfo dbus_glib_%s_object_info = {\n",
|
||||
channel, error, interface_c_name))
|
||||
goto io_lose;
|
||||
WRITE_OR_LOSE (" 0,\n");
|
||||
if (!write_printf_to_iochannel (" dbus_glib_%s_methods,\n", channel, error, interface_c_name))
|
||||
goto io_lose;
|
||||
if (!write_printf_to_iochannel (" %d,\n", channel, error, count))
|
||||
goto io_lose;
|
||||
WRITE_OR_LOSE(" \"");
|
||||
for (i = 0; i < object_introspection_data_blob->len; i++)
|
||||
{
|
||||
if (object_introspection_data_blob->str[i] != '\0')
|
||||
{
|
||||
if (!g_io_channel_write_chars (channel, object_introspection_data_blob->str + i, 1, NULL, error))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!g_io_channel_write_chars (channel, "\\0", -1, NULL, error))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
WRITE_OR_LOSE ("\"\n};\n\n");
|
||||
|
||||
g_string_free (object_introspection_data_blob, TRUE);
|
||||
}
|
||||
return TRUE;
|
||||
io_lose:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
write_marshaller (gpointer key, gpointer value, gpointer user_data)
|
||||
{
|
||||
DBusBindingToolCData *data;
|
||||
const char *marshaller;
|
||||
gsize bytes_written;
|
||||
|
||||
data = user_data;
|
||||
marshaller = key;
|
||||
|
||||
if (data->error && *data->error)
|
||||
return;
|
||||
|
||||
if (g_io_channel_write_chars (data->channel, marshaller, -1, &bytes_written, data->error) == G_IO_STATUS_NORMAL)
|
||||
g_io_channel_write_chars (data->channel, "\n", -1, &bytes_written, data->error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
dbus_binding_tool_output_glib_server (BaseInfo *info, GIOChannel *channel, GError **error)
|
||||
{
|
||||
gboolean ret;
|
||||
GPtrArray *argv;
|
||||
gint child_stdout;
|
||||
GIOChannel *genmarshal_stdout;
|
||||
GPid child_pid;
|
||||
DBusBindingToolCData data;
|
||||
char *tempfile_name;
|
||||
gint tempfile_fd;
|
||||
GIOStatus iostatus;
|
||||
char buf[4096];
|
||||
gsize bytes_read, bytes_written;
|
||||
|
||||
memset (&data, 0, sizeof (data));
|
||||
|
||||
data.generated = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
|
||||
data.error = error;
|
||||
genmarshal_stdout = NULL;
|
||||
tempfile_name = NULL;
|
||||
|
||||
if (!gather_marshallers (info, &data, error))
|
||||
goto io_lose;
|
||||
|
||||
tempfile_fd = g_file_open_tmp ("dbus-binding-tool-c-marshallers.XXXXXX",
|
||||
&tempfile_name, error);
|
||||
if (tempfile_fd < 0)
|
||||
goto io_lose;
|
||||
|
||||
data.channel = g_io_channel_unix_new (tempfile_fd);
|
||||
if (!g_io_channel_set_encoding (data.channel, NULL, error))
|
||||
goto io_lose;
|
||||
g_hash_table_foreach (data.generated, write_marshaller, &data);
|
||||
if (error && *error != NULL)
|
||||
{
|
||||
ret = FALSE;
|
||||
g_io_channel_close (data.channel);
|
||||
g_io_channel_unref (data.channel);
|
||||
goto io_lose;
|
||||
}
|
||||
|
||||
g_io_channel_close (data.channel);
|
||||
g_io_channel_unref (data.channel);
|
||||
|
||||
/* Now spawn glib-genmarshal to insert all our required marshallers */
|
||||
argv = g_ptr_array_new ();
|
||||
g_ptr_array_add (argv, "glib-genmarshal");
|
||||
g_ptr_array_add (argv, "--header");
|
||||
g_ptr_array_add (argv, "--body");
|
||||
g_ptr_array_add (argv, "--prefix=" MARSHAL_PREFIX);
|
||||
g_ptr_array_add (argv, tempfile_name);
|
||||
g_ptr_array_add (argv, NULL);
|
||||
if (!g_spawn_async_with_pipes (NULL, (char**)argv->pdata, NULL,
|
||||
G_SPAWN_SEARCH_PATH,
|
||||
NULL, NULL,
|
||||
&child_pid,
|
||||
NULL,
|
||||
&child_stdout, NULL, error))
|
||||
{
|
||||
g_ptr_array_free (argv, TRUE);
|
||||
goto io_lose;
|
||||
}
|
||||
g_ptr_array_free (argv, TRUE);
|
||||
|
||||
genmarshal_stdout = g_io_channel_unix_new (child_stdout);
|
||||
if (!g_io_channel_set_encoding (genmarshal_stdout, NULL, error))
|
||||
goto io_lose;
|
||||
|
||||
WRITE_OR_LOSE ("/* Generated by dbus-binding-tool; do not edit! */\n\n");
|
||||
|
||||
while ((iostatus = g_io_channel_read_chars (genmarshal_stdout, buf, sizeof (buf),
|
||||
&bytes_read, error)) == G_IO_STATUS_NORMAL)
|
||||
if (g_io_channel_write_chars (channel, buf, bytes_read, &bytes_written, error) != G_IO_STATUS_NORMAL)
|
||||
goto io_lose;
|
||||
if (iostatus != G_IO_STATUS_EOF)
|
||||
goto io_lose;
|
||||
|
||||
g_io_channel_close (genmarshal_stdout);
|
||||
|
||||
WRITE_OR_LOSE ("#include <dbus/dbus-glib.h>\n");
|
||||
|
||||
g_io_channel_ref (data.channel);
|
||||
data.channel = channel;
|
||||
if (!generate_glue (info, &data, error))
|
||||
goto io_lose;
|
||||
|
||||
ret = TRUE;
|
||||
cleanup:
|
||||
if (tempfile_name)
|
||||
unlink (tempfile_name);
|
||||
g_free (tempfile_name);
|
||||
if (genmarshal_stdout)
|
||||
g_io_channel_unref (genmarshal_stdout);
|
||||
if (data.channel)
|
||||
g_io_channel_unref (data.channel);
|
||||
g_hash_table_destroy (data.generated);
|
||||
|
||||
return ret;
|
||||
io_lose:
|
||||
ret = FALSE;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
static char *
|
||||
iface_to_c_prefix (const char *iface)
|
||||
{
|
||||
char **components;
|
||||
char **component;
|
||||
GString *ret;
|
||||
gboolean first;
|
||||
|
||||
components = g_strsplit (iface, ".", 0);
|
||||
|
||||
first = TRUE;
|
||||
ret = g_string_new ("");
|
||||
for (component = components; *component; component++)
|
||||
{
|
||||
if (!first)
|
||||
g_string_append_c (ret, '_');
|
||||
else
|
||||
first = FALSE;
|
||||
g_string_append (ret, *component);
|
||||
}
|
||||
g_strfreev (components);
|
||||
return g_string_free (ret, FALSE);
|
||||
}
|
||||
|
||||
static char *
|
||||
compute_client_method_name (InterfaceInfo *iface, MethodInfo *method)
|
||||
{
|
||||
GString *ret;
|
||||
char *method_name_uscored;
|
||||
char *iface_prefix;
|
||||
|
||||
iface_prefix = iface_to_c_prefix (interface_info_get_name (iface));
|
||||
ret = g_string_new (iface_prefix);
|
||||
g_free (iface_prefix);
|
||||
|
||||
method_name_uscored = _dbus_gutils_wincaps_to_uscore (method_info_get_name (method));
|
||||
g_string_append_c (ret, '_');
|
||||
g_string_append (ret, method_name_uscored);
|
||||
g_free (method_name_uscored);
|
||||
return g_string_free (ret, FALSE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
write_formal_parameters (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, GError **error)
|
||||
{
|
||||
GSList *args;
|
||||
|
||||
for (args = method_info_get_args (method); args; args = args->next)
|
||||
{
|
||||
ArgInfo *arg;
|
||||
const char *type_str;
|
||||
int direction;
|
||||
|
||||
arg = args->data;
|
||||
|
||||
WRITE_OR_LOSE (", ");
|
||||
|
||||
direction = arg_info_get_direction (arg);
|
||||
|
||||
/* FIXME - broken for containers */
|
||||
type_str = dbus_gvalue_ctype_from_type (arg_info_get_type (arg), direction == ARG_IN);
|
||||
|
||||
if (!type_str)
|
||||
{
|
||||
g_set_error (error,
|
||||
DBUS_BINDING_TOOL_ERROR,
|
||||
DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
|
||||
_("Unsupported conversion from D-BUS type %d to glib C type"),
|
||||
arg_info_get_type (arg));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (direction)
|
||||
{
|
||||
case ARG_IN:
|
||||
if (!write_printf_to_iochannel ("%s IN_%s", channel, error,
|
||||
type_str,
|
||||
arg_info_get_name (arg)))
|
||||
goto io_lose;
|
||||
break;
|
||||
case ARG_OUT:
|
||||
if (!write_printf_to_iochannel ("%s* OUT_%s", channel, error,
|
||||
type_str,
|
||||
arg_info_get_name (arg)))
|
||||
goto io_lose;
|
||||
break;
|
||||
case ARG_INVALID:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
io_lose:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
write_args_for_direction (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, int direction, GError **error)
|
||||
{
|
||||
GSList *args;
|
||||
|
||||
for (args = method_info_get_args (method); args; args = args->next)
|
||||
{
|
||||
ArgInfo *arg;
|
||||
const char *type_str;
|
||||
|
||||
arg = args->data;
|
||||
|
||||
if (direction != arg_info_get_direction (arg))
|
||||
continue;
|
||||
|
||||
/* FIXME - broken for containers */
|
||||
type_str = dbus_gvalue_binding_type_from_type (arg_info_get_type (arg));
|
||||
if (!type_str)
|
||||
{
|
||||
g_set_error (error,
|
||||
DBUS_BINDING_TOOL_ERROR,
|
||||
DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
|
||||
_("Unsupported conversion from D-BUS type %c"),
|
||||
(char) arg_info_get_type (arg));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
switch (direction)
|
||||
{
|
||||
case ARG_IN:
|
||||
if (!write_printf_to_iochannel (" %s, &IN_%s,\n", channel, error,
|
||||
type_str, arg_info_get_name (arg)))
|
||||
goto io_lose;
|
||||
break;
|
||||
case ARG_OUT:
|
||||
if (!write_printf_to_iochannel (" %s, OUT_%s,\n", channel, error,
|
||||
type_str, arg_info_get_name (arg)))
|
||||
goto io_lose;
|
||||
break;
|
||||
case ARG_INVALID:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
io_lose:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
generate_client_glue_list (GSList *list, DBusBindingToolCData *data, GError **error)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
tmp = list;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
if (!generate_client_glue (tmp->data, data, error))
|
||||
return FALSE;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
generate_client_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
|
||||
{
|
||||
if (base_info_get_type (base) == INFO_TYPE_NODE)
|
||||
{
|
||||
if (!generate_client_glue_list (node_info_get_nodes ((NodeInfo *) base),
|
||||
data, error))
|
||||
return FALSE;
|
||||
if (!generate_client_glue_list (node_info_get_interfaces ((NodeInfo *) base),
|
||||
data, error))
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
GIOChannel *channel;
|
||||
InterfaceInfo *interface;
|
||||
GSList *methods;
|
||||
GSList *tmp;
|
||||
int count;
|
||||
|
||||
channel = data->channel;
|
||||
|
||||
interface = (InterfaceInfo *) base;
|
||||
|
||||
methods = interface_info_get_methods (interface);
|
||||
count = 0;
|
||||
|
||||
for (tmp = methods; tmp != NULL; tmp = g_slist_next (tmp))
|
||||
{
|
||||
MethodInfo *method;
|
||||
char *method_name;
|
||||
|
||||
method = (MethodInfo *) tmp->data;
|
||||
|
||||
method_name = compute_client_method_name (interface, method);
|
||||
|
||||
WRITE_OR_LOSE ("static gboolean\n");
|
||||
if (!write_printf_to_iochannel ("%s (DBusGProxy *proxy", channel, error,
|
||||
method_name))
|
||||
goto io_lose;
|
||||
g_free (method_name);
|
||||
|
||||
if (!write_formal_parameters (interface, method, channel, error))
|
||||
goto io_lose;
|
||||
|
||||
WRITE_OR_LOSE (", GError **error)\n\n");
|
||||
|
||||
WRITE_OR_LOSE ("{\n");
|
||||
WRITE_OR_LOSE (" gboolean ret;\n\n");
|
||||
WRITE_OR_LOSE (" DBusGPendingCall *call;\n\n");
|
||||
|
||||
if (!write_printf_to_iochannel (" call = dbus_g_proxy_begin_call (proxy, \"%s\",\n",
|
||||
channel, error,
|
||||
method_info_get_name (method)))
|
||||
goto io_lose;
|
||||
|
||||
if (!write_args_for_direction (interface, method, channel, ARG_IN, error))
|
||||
goto io_lose;
|
||||
|
||||
WRITE_OR_LOSE (" DBUS_TYPE_INVALID);\n");
|
||||
WRITE_OR_LOSE (" ret = dbus_g_proxy_end_call (proxy, call, error,\n");
|
||||
|
||||
if (!write_args_for_direction (interface, method, channel, ARG_OUT, error))
|
||||
goto io_lose;
|
||||
|
||||
WRITE_OR_LOSE (" DBUS_TYPE_INVALID);\n");
|
||||
|
||||
WRITE_OR_LOSE (" dbus_g_pending_call_unref (call);\n");
|
||||
WRITE_OR_LOSE (" return ret;\n");
|
||||
|
||||
WRITE_OR_LOSE ("}\n\n");
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
io_lose:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
dbus_binding_tool_output_glib_client (BaseInfo *info, GIOChannel *channel, GError **error)
|
||||
{
|
||||
DBusBindingToolCData data;
|
||||
gboolean ret;
|
||||
|
||||
memset (&data, 0, sizeof (data));
|
||||
|
||||
data.channel = channel;
|
||||
|
||||
WRITE_OR_LOSE ("/* Generated by dbus-binding-tool; do not edit! */\n\n");
|
||||
WRITE_OR_LOSE ("#include <glib/gtypes.h>\n");
|
||||
WRITE_OR_LOSE ("#include <glib/gerror.h>\n");
|
||||
WRITE_OR_LOSE ("#include <dbus/dbus-glib.h>\n\n");
|
||||
|
||||
ret = generate_client_glue (info, &data, error);
|
||||
|
||||
return ret;
|
||||
io_lose:
|
||||
return FALSE;
|
||||
}
|
||||
33
glib/dbus-binding-tool-glib.h
Normal file
33
glib/dbus-binding-tool-glib.h
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/* -*- mode: C; c-file-style: "gnu" -*- */
|
||||
/* dbus-binding-tool-output-glib.h prototypes for glib output
|
||||
*
|
||||
* Copyright (C) 2005 Red Hat, Inc.
|
||||
*
|
||||
* Licensed under the Academic Free License version 2.1
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#ifndef DBUS_BINDING_TOOL_OUTPUT_GLIB_H
|
||||
#define DBUS_BINDING_TOOL_OUTPUT_GLIB_H
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gboolean dbus_binding_tool_output_glib_client (BaseInfo *info, GIOChannel *channel, GError **error);
|
||||
gboolean dbus_binding_tool_output_glib_server (BaseInfo *info, GIOChannel *channel, GError **error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
|
@ -43,6 +43,7 @@ struct NodeInfo
|
|||
struct InterfaceInfo
|
||||
{
|
||||
BaseInfo base;
|
||||
GHashTable *bindings;
|
||||
/* Since we have BaseInfo now these could be one list */
|
||||
GSList *methods;
|
||||
GSList *signals;
|
||||
|
|
@ -52,6 +53,7 @@ struct InterfaceInfo
|
|||
struct MethodInfo
|
||||
{
|
||||
BaseInfo base;
|
||||
GHashTable *bindings;
|
||||
GSList *args;
|
||||
};
|
||||
|
||||
|
|
@ -75,6 +77,23 @@ struct ArgInfo
|
|||
ArgDirection direction;
|
||||
};
|
||||
|
||||
static void
|
||||
get_hash_key (gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
GSList **list = data;
|
||||
*list = g_slist_prepend (*list, key);
|
||||
}
|
||||
|
||||
static GSList *
|
||||
get_hash_keys (GHashTable *table)
|
||||
{
|
||||
GSList *ret = NULL;
|
||||
|
||||
g_hash_table_foreach (table, get_hash_key, &ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BaseInfo *
|
||||
base_info_ref (BaseInfo *info)
|
||||
{
|
||||
|
|
@ -326,6 +345,9 @@ interface_info_new (const char *name)
|
|||
info->base.refcount = 1;
|
||||
info->base.name = g_strdup (name);
|
||||
info->base.type = INFO_TYPE_INTERFACE;
|
||||
info->bindings = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
(GDestroyNotify) g_free,
|
||||
(GDestroyNotify) g_free);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
|
@ -344,6 +366,7 @@ interface_info_unref (InterfaceInfo *info)
|
|||
info->base.refcount -= 1;
|
||||
if (info->base.refcount == 0)
|
||||
{
|
||||
g_hash_table_destroy (info->bindings);
|
||||
free_method_list (&info->methods);
|
||||
free_signal_list (&info->signals);
|
||||
free_property_list (&info->properties);
|
||||
|
|
@ -357,6 +380,19 @@ interface_info_get_name (InterfaceInfo *info)
|
|||
return info->base.name;
|
||||
}
|
||||
|
||||
GSList *
|
||||
interface_info_get_binding_names (InterfaceInfo *info)
|
||||
{
|
||||
return get_hash_keys (info->bindings);
|
||||
}
|
||||
|
||||
const char*
|
||||
interface_info_get_binding_name (InterfaceInfo *info,
|
||||
const char *binding_type)
|
||||
{
|
||||
return g_hash_table_lookup (info->bindings, binding_type);
|
||||
}
|
||||
|
||||
GSList*
|
||||
interface_info_get_methods (InterfaceInfo *info)
|
||||
{
|
||||
|
|
@ -375,6 +411,16 @@ interface_info_get_properties (InterfaceInfo *info)
|
|||
return info->properties;
|
||||
}
|
||||
|
||||
void
|
||||
interface_info_set_binding_name (InterfaceInfo *info,
|
||||
const char *binding_type,
|
||||
const char *bound_name)
|
||||
{
|
||||
g_hash_table_insert (info->bindings,
|
||||
g_strdup (binding_type),
|
||||
g_strdup (bound_name));
|
||||
}
|
||||
|
||||
void
|
||||
interface_info_add_method (InterfaceInfo *info,
|
||||
MethodInfo *method)
|
||||
|
|
@ -424,6 +470,9 @@ method_info_new (const char *name)
|
|||
info->base.refcount = 1;
|
||||
info->base.name = g_strdup (name);
|
||||
info->base.type = INFO_TYPE_METHOD;
|
||||
info->bindings = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
(GDestroyNotify) g_free,
|
||||
(GDestroyNotify) g_free);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
|
@ -442,6 +491,7 @@ method_info_unref (MethodInfo *info)
|
|||
info->base.refcount -= 1;
|
||||
if (info->base.refcount == 0)
|
||||
{
|
||||
g_hash_table_destroy (info->bindings);
|
||||
free_arg_list (&info->args);
|
||||
base_info_free (info);
|
||||
}
|
||||
|
|
@ -453,6 +503,19 @@ method_info_get_name (MethodInfo *info)
|
|||
return info->base.name;
|
||||
}
|
||||
|
||||
GSList *
|
||||
method_info_get_binding_names (MethodInfo *info)
|
||||
{
|
||||
return get_hash_keys (info->bindings);
|
||||
}
|
||||
|
||||
const char*
|
||||
method_info_get_binding_name (MethodInfo *info,
|
||||
const char *binding_type)
|
||||
{
|
||||
return g_hash_table_lookup (info->bindings, binding_type);
|
||||
}
|
||||
|
||||
GSList*
|
||||
method_info_get_args (MethodInfo *info)
|
||||
{
|
||||
|
|
@ -480,6 +543,16 @@ args_sort_by_direction (const void *a,
|
|||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
method_info_set_binding_name (MethodInfo *info,
|
||||
const char *binding_type,
|
||||
const char *bound_name)
|
||||
{
|
||||
g_hash_table_insert (info->bindings,
|
||||
g_strdup (binding_type),
|
||||
g_strdup (bound_name));
|
||||
}
|
||||
|
||||
void
|
||||
method_info_add_arg (MethodInfo *info,
|
||||
ArgInfo *arg)
|
||||
|
|
|
|||
|
|
@ -90,19 +90,31 @@ InterfaceInfo* interface_info_new (const char *name);
|
|||
InterfaceInfo* interface_info_ref (InterfaceInfo *info);
|
||||
void interface_info_unref (InterfaceInfo *info);
|
||||
const char* interface_info_get_name (InterfaceInfo *info);
|
||||
GSList* interface_info_get_binding_names(InterfaceInfo *info);
|
||||
const char* interface_info_get_binding_name(InterfaceInfo*info,
|
||||
const char *binding_type);
|
||||
GSList* interface_info_get_methods (InterfaceInfo *info);
|
||||
GSList* interface_info_get_signals (InterfaceInfo *info);
|
||||
GSList* interface_info_get_properties (InterfaceInfo *info);
|
||||
void interface_info_set_binding_name(InterfaceInfo *info,
|
||||
const char *name,
|
||||
const char *value);
|
||||
void interface_info_add_method (InterfaceInfo *info,
|
||||
MethodInfo *method);
|
||||
void interface_info_add_signal (InterfaceInfo *info,
|
||||
SignalInfo *signal);
|
||||
void interface_info_add_property (InterfaceInfo *info,
|
||||
PropertyInfo *property);
|
||||
MethodInfo* method_info_new (const char *name);
|
||||
MethodInfo* method_info_new (const char *name);
|
||||
MethodInfo* method_info_ref (MethodInfo *info);
|
||||
void method_info_unref (MethodInfo *info);
|
||||
const char* method_info_get_name (MethodInfo *info);
|
||||
GSList* method_info_get_binding_names (MethodInfo *info);
|
||||
const char* method_info_get_binding_name (MethodInfo *info,
|
||||
const char *binding_type);
|
||||
void method_info_set_binding_name (MethodInfo *info,
|
||||
const char *binding_type,
|
||||
const char *bound_name);
|
||||
GSList* method_info_get_args (MethodInfo *info);
|
||||
void method_info_add_arg (MethodInfo *info,
|
||||
ArgInfo *arg);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "dbus-gidl.h"
|
||||
#include "dbus-gparser.h"
|
||||
#include "dbus-gutils.h"
|
||||
#include "dbus-binding-tool-glib.h"
|
||||
#include <locale.h>
|
||||
#include <libintl.h>
|
||||
#define _(x) dgettext (GETTEXT_PACKAGE, x)
|
||||
|
|
@ -37,6 +38,13 @@
|
|||
static void run_all_tests (const char *test_data_dir);
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
DBUS_BINDING_OUTPUT_NONE,
|
||||
DBUS_BINDING_OUTPUT_PRETTY,
|
||||
DBUS_BINDING_OUTPUT_GLIB_SERVER,
|
||||
DBUS_BINDING_OUTPUT_GLIB_CLIENT,
|
||||
} DBusBindingOutputMode;
|
||||
|
||||
static void
|
||||
indent (int depth)
|
||||
{
|
||||
|
|
@ -99,11 +107,23 @@ pretty_print (BaseInfo *base,
|
|||
case INFO_TYPE_INTERFACE:
|
||||
{
|
||||
InterfaceInfo *i = (InterfaceInfo*) base;
|
||||
GSList *binding_types, *elt;
|
||||
|
||||
g_assert (name != NULL);
|
||||
|
||||
printf (_("interface \"%s\" {\n"), name);
|
||||
|
||||
binding_types = interface_info_get_binding_names (i);
|
||||
for (elt = binding_types; elt; elt = elt->next)
|
||||
{
|
||||
const char *binding_type = elt->data;
|
||||
const char *binding_name = interface_info_get_binding_name (i, binding_type);
|
||||
|
||||
printf (_(" (binding \"%s\": \"%s\") "),
|
||||
binding_type, binding_name);
|
||||
}
|
||||
g_slist_free (binding_types);
|
||||
|
||||
pretty_print_list (interface_info_get_methods (i), depth + 1);
|
||||
pretty_print_list (interface_info_get_signals (i), depth + 1);
|
||||
pretty_print_list (interface_info_get_properties (i), depth + 1);
|
||||
|
|
@ -115,10 +135,21 @@ pretty_print (BaseInfo *base,
|
|||
case INFO_TYPE_METHOD:
|
||||
{
|
||||
MethodInfo *m = (MethodInfo*) base;
|
||||
GSList *binding_types, *elt;
|
||||
|
||||
g_assert (name != NULL);
|
||||
|
||||
printf (_("method \"%s\" (\n"), name);
|
||||
binding_types = method_info_get_binding_names (m);
|
||||
printf (_("method \"%s\""), name);
|
||||
for (elt = binding_types; elt; elt = elt->next)
|
||||
{
|
||||
const char *binding_type = elt->data;
|
||||
const char *binding_name = method_info_get_binding_name (m, binding_type);
|
||||
|
||||
printf (_(" (binding \"%s\": \"%s\") "),
|
||||
binding_type, binding_name);
|
||||
}
|
||||
g_slist_free (binding_types);
|
||||
|
||||
pretty_print_list (method_info_get_args (m), depth + 1);
|
||||
|
||||
|
|
@ -174,6 +205,16 @@ pretty_print (BaseInfo *base,
|
|||
}
|
||||
}
|
||||
|
||||
GQuark
|
||||
dbus_binding_tool_error_quark (void)
|
||||
{
|
||||
static GQuark quark = 0;
|
||||
if (!quark)
|
||||
quark = g_quark_from_static_string ("dbus_binding_tool_error");
|
||||
|
||||
return quark;
|
||||
}
|
||||
|
||||
static void
|
||||
usage (int ecode)
|
||||
{
|
||||
|
|
@ -186,7 +227,7 @@ version (void)
|
|||
{
|
||||
printf ("D-BUS Binding Tool %s\n"
|
||||
"Copyright (C) 2003-2005 Red Hat, Inc.\n"
|
||||
"This is free software; xsee the source for copying conditions.\n"
|
||||
"This is free software; see the source for copying conditions.\n"
|
||||
"There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n",
|
||||
VERSION);
|
||||
exit (0);
|
||||
|
|
@ -198,16 +239,20 @@ main (int argc, char **argv)
|
|||
const char *prev_arg;
|
||||
int i;
|
||||
GSList *files;
|
||||
DBusBindingOutputMode outputmode;
|
||||
gboolean end_of_args;
|
||||
GSList *tmp;
|
||||
gboolean just_pretty_print;
|
||||
GIOChannel *channel;
|
||||
GError *error;
|
||||
|
||||
setlocale (LC_ALL, "");
|
||||
bindtextdomain (GETTEXT_PACKAGE, DBUS_LOCALEDIR);
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
textdomain (GETTEXT_PACKAGE);
|
||||
|
||||
just_pretty_print = FALSE;
|
||||
g_type_init ();
|
||||
|
||||
outputmode = DBUS_BINDING_OUTPUT_NONE;
|
||||
end_of_args = FALSE;
|
||||
files = NULL;
|
||||
prev_arg = NULL;
|
||||
|
|
@ -228,8 +273,18 @@ main (int argc, char **argv)
|
|||
else if (strcmp (arg, "--self-test") == 0)
|
||||
run_all_tests (NULL);
|
||||
#endif /* DBUS_BUILD_TESTS */
|
||||
else if (strcmp (arg, "--pretty-print") == 0)
|
||||
just_pretty_print = TRUE;
|
||||
else if (strncmp (arg, "--mode=", 7) == 0)
|
||||
{
|
||||
const char *mode = arg + 7;
|
||||
if (!strcmp (mode, "pretty"))
|
||||
outputmode = DBUS_BINDING_OUTPUT_PRETTY;
|
||||
else if (!strcmp (mode, "glib-server"))
|
||||
outputmode = DBUS_BINDING_OUTPUT_GLIB_SERVER;
|
||||
else if (!strcmp (mode, "glib-client"))
|
||||
outputmode = DBUS_BINDING_OUTPUT_GLIB_CLIENT;
|
||||
else
|
||||
usage (1);
|
||||
}
|
||||
else if (arg[0] == '-' &&
|
||||
arg[1] == '-' &&
|
||||
arg[2] == '\0')
|
||||
|
|
@ -251,6 +306,15 @@ main (int argc, char **argv)
|
|||
++i;
|
||||
}
|
||||
|
||||
error = NULL;
|
||||
channel = g_io_channel_unix_new (fileno (stdout));
|
||||
if (!g_io_channel_set_encoding (channel, NULL, &error))
|
||||
{
|
||||
fprintf (stderr, _("Couldn't set channel encoding to NULL: %s\n"),
|
||||
error->message);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
files = g_slist_reverse (files);
|
||||
|
||||
tmp = files;
|
||||
|
|
@ -273,27 +337,43 @@ main (int argc, char **argv)
|
|||
g_error_free (error);
|
||||
exit (1);
|
||||
}
|
||||
else if (just_pretty_print)
|
||||
{
|
||||
pretty_print ((BaseInfo*) node, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME process the file to generate metadata variable
|
||||
* definition rather than just printing it.
|
||||
* i.e. we want to create DBusGObjectInfo.
|
||||
* This probably requires extending the introspection XML format to
|
||||
* allow a "native function name":
|
||||
* <method name="Frobate" native="my_object_frobate">
|
||||
*/
|
||||
pretty_print ((BaseInfo*) node, 0);
|
||||
}
|
||||
{
|
||||
switch (outputmode)
|
||||
{
|
||||
case DBUS_BINDING_OUTPUT_PRETTY:
|
||||
pretty_print ((BaseInfo*) node, 0);
|
||||
break;
|
||||
case DBUS_BINDING_OUTPUT_GLIB_SERVER:
|
||||
if (!dbus_binding_tool_output_glib_server ((BaseInfo *) node, channel, &error))
|
||||
{
|
||||
g_error (_("Compilation failed: %s\n"), error->message);
|
||||
exit (1);
|
||||
}
|
||||
break;
|
||||
case DBUS_BINDING_OUTPUT_GLIB_CLIENT:
|
||||
if (!dbus_binding_tool_output_glib_client ((BaseInfo *) node, channel, &error))
|
||||
{
|
||||
g_error (_("Compilation failed: %s\n"), error->message);
|
||||
exit (1);
|
||||
}
|
||||
break;
|
||||
case DBUS_BINDING_OUTPUT_NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (node)
|
||||
node_info_unref (node);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
if (!g_io_channel_flush (channel, &error))
|
||||
{
|
||||
g_error (_("Failed to flush IO channel: %s"), error->message);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
37
glib/dbus-glib-tool.h
Normal file
37
glib/dbus-glib-tool.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/* -*- mode: C; c-file-style: "gnu" -*- */
|
||||
/* dbus-glib-tool.h: Definitions used internally by binding tool
|
||||
*
|
||||
* Copyright (C) 2005 Red Hat, Inc.
|
||||
*
|
||||
* Licensed under the Academic Free License version 2.1
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#ifndef DBUS_BINDING_TOOL_H
|
||||
#define DBUS_BINDING_TOOL_H
|
||||
|
||||
#include <glib/gquark.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION
|
||||
} DBusBindingToolError;
|
||||
|
||||
#define DBUS_BINDING_TOOL_ERROR dbus_binding_tool_error_quark ()
|
||||
|
||||
GQuark dbus_binding_tool_error_quark (void);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
/* -*- mode: C; c-file-style: "gnu" -*- */
|
||||
/* dbus-gobject.c Exporting a GObject remotely
|
||||
*
|
||||
* Copyright (C) 2003, 2004 Red Hat, Inc.
|
||||
* Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
|
||||
*
|
||||
* Licensed under the Academic Free License version 2.1
|
||||
*
|
||||
|
|
@ -26,6 +26,7 @@
|
|||
#include <dbus/dbus-glib-lowlevel.h>
|
||||
#include "dbus-gtest.h"
|
||||
#include "dbus-gutils.h"
|
||||
#include "dbus-gobject.h"
|
||||
#include "dbus-gvalue.h"
|
||||
#include <string.h>
|
||||
|
||||
|
|
@ -34,36 +35,9 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
static GStaticMutex info_hash_mutex = G_STATIC_MUTEX_INIT;
|
||||
static GStaticRWLock info_hash_lock = G_STATIC_RW_LOCK_INIT;
|
||||
static GHashTable *info_hash = NULL;
|
||||
|
||||
static char*
|
||||
wincaps_to_uscore (const char *caps)
|
||||
{
|
||||
const char *p;
|
||||
GString *str;
|
||||
|
||||
str = g_string_new (NULL);
|
||||
p = caps;
|
||||
while (*p)
|
||||
{
|
||||
if (g_ascii_isupper (*p))
|
||||
{
|
||||
if (str->len > 0 &&
|
||||
(str->len < 2 || str->str[str->len-2] != '_'))
|
||||
g_string_append_c (str, '_');
|
||||
g_string_append_c (str, g_ascii_tolower (*p));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_string_append_c (str, *p);
|
||||
}
|
||||
++p;
|
||||
}
|
||||
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
static char*
|
||||
uscore_to_wincaps (const char *uscore)
|
||||
{
|
||||
|
|
@ -97,6 +71,164 @@ uscore_to_wincaps (const char *uscore)
|
|||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
static const char *
|
||||
string_table_next (const char *table)
|
||||
{
|
||||
return (table + (strlen (table) + 1));
|
||||
}
|
||||
|
||||
static const char *
|
||||
string_table_lookup (const char *table, int index)
|
||||
{
|
||||
const char *ret;
|
||||
|
||||
ret = table;
|
||||
|
||||
while (index--)
|
||||
ret = string_table_next (ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_method_data (const DBusGObjectInfo *object,
|
||||
const DBusGMethodInfo *method)
|
||||
{
|
||||
return object->data + method->data_offset;
|
||||
}
|
||||
|
||||
static char *
|
||||
object_error_domain_prefix_from_object_info (const DBusGObjectInfo *info)
|
||||
{
|
||||
/* FIXME */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *
|
||||
object_error_code_from_object_info (const DBusGObjectInfo *info, GQuark domain, gint code)
|
||||
{
|
||||
/* FIXME */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *
|
||||
method_interface_from_object_info (const DBusGObjectInfo *object,
|
||||
const DBusGMethodInfo *method)
|
||||
{
|
||||
return string_table_lookup (get_method_data (object, method), 0);
|
||||
}
|
||||
|
||||
static const char *
|
||||
method_name_from_object_info (const DBusGObjectInfo *object,
|
||||
const DBusGMethodInfo *method)
|
||||
{
|
||||
return string_table_lookup (get_method_data (object, method), 1);
|
||||
}
|
||||
|
||||
static const char *
|
||||
method_arg_info_from_object_info (const DBusGObjectInfo *object,
|
||||
const DBusGMethodInfo *method)
|
||||
{
|
||||
return string_table_lookup (get_method_data (object, method), 2);
|
||||
}
|
||||
|
||||
static const char *
|
||||
arg_iterate (const char *data, const char **name, gboolean *in,
|
||||
const char **type)
|
||||
{
|
||||
*name = data;
|
||||
|
||||
data = string_table_next (data);
|
||||
switch (*data)
|
||||
{
|
||||
case 'I':
|
||||
*in = TRUE;
|
||||
break;
|
||||
case 'O':
|
||||
*in = FALSE;
|
||||
break;
|
||||
default:
|
||||
g_warning ("invalid arg direction");
|
||||
break;
|
||||
}
|
||||
|
||||
data = string_table_next (data);
|
||||
*type = data;
|
||||
|
||||
return string_table_next (data);
|
||||
}
|
||||
|
||||
static char *
|
||||
method_dir_signature_from_object_info (const DBusGObjectInfo *object,
|
||||
const DBusGMethodInfo *method,
|
||||
gboolean in)
|
||||
{
|
||||
const char *arg;
|
||||
GString *ret;
|
||||
|
||||
arg = method_arg_info_from_object_info (object, method);
|
||||
|
||||
ret = g_string_new (NULL);
|
||||
|
||||
while (*arg)
|
||||
{
|
||||
const char *name;
|
||||
gboolean arg_in;
|
||||
const char *type;
|
||||
|
||||
arg = arg_iterate (arg, &name, &arg_in, &type);
|
||||
|
||||
if (arg_in == in)
|
||||
g_string_append (ret, type);
|
||||
}
|
||||
|
||||
return g_string_free (ret, FALSE);
|
||||
}
|
||||
|
||||
static char *
|
||||
method_input_signature_from_object_info (const DBusGObjectInfo *object,
|
||||
const DBusGMethodInfo *method)
|
||||
{
|
||||
return method_dir_signature_from_object_info (object, method, TRUE);
|
||||
}
|
||||
|
||||
static char *
|
||||
method_output_signature_from_object_info (const DBusGObjectInfo *object,
|
||||
const DBusGMethodInfo *method)
|
||||
{
|
||||
return method_dir_signature_from_object_info (object, method, FALSE);
|
||||
}
|
||||
|
||||
GValueArray *
|
||||
dbus_glib_marshal_dbus_message_to_gvalue_array (DBusMessage *message)
|
||||
{
|
||||
GValueArray *ret;
|
||||
DBusMessageIter iter;
|
||||
int dtype;
|
||||
|
||||
ret = g_value_array_new (6); /* 6 is a typical maximum for arguments */
|
||||
dbus_message_iter_init (message, &iter);
|
||||
|
||||
while ((dtype = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
|
||||
{
|
||||
GValue value = { 0, };
|
||||
|
||||
if (!dbus_gvalue_demarshal (&iter, &value))
|
||||
{
|
||||
g_warning ("Unable to convert arg type %d to GValue", dtype);
|
||||
g_value_array_free (ret);
|
||||
ret = NULL;
|
||||
goto out;
|
||||
}
|
||||
g_value_array_append (ret, &value);
|
||||
|
||||
dbus_message_iter_next (&iter);
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
gobject_unregister_function (DBusConnection *connection,
|
||||
void *user_data)
|
||||
|
|
@ -272,6 +404,115 @@ introspect_signals (GType type, GString *xml)
|
|||
g_string_append (xml, " </interface>\n");
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GString *xml;
|
||||
const DBusGObjectInfo *object_info;
|
||||
} DBusGlibWriteIterfaceData;
|
||||
|
||||
static void
|
||||
write_interface (gpointer key, gpointer val, gpointer user_data)
|
||||
{
|
||||
const char *name;
|
||||
GSList *methods;
|
||||
GString *xml;
|
||||
const DBusGObjectInfo *object_info;
|
||||
DBusGlibWriteIterfaceData *data;
|
||||
|
||||
name = key;
|
||||
methods = val;
|
||||
data = user_data;
|
||||
xml = data->xml;
|
||||
object_info = data->object_info;
|
||||
|
||||
g_string_append_printf (xml, " <interface name=\"%s\">\n", name);
|
||||
|
||||
/* FIXME: recurse to parent types ? */
|
||||
for (; methods; methods = methods->next)
|
||||
{
|
||||
DBusGMethodInfo *method;
|
||||
method = methods->data;
|
||||
const char *args;
|
||||
|
||||
g_string_append_printf (xml, " <method name=\"%s\">\n",
|
||||
method_name_from_object_info (object_info, method));
|
||||
|
||||
args = method_arg_info_from_object_info (object_info, method);
|
||||
|
||||
while (*args)
|
||||
{
|
||||
const char *name;
|
||||
gboolean arg_in;
|
||||
const char *type;
|
||||
|
||||
args = arg_iterate (args, &name, &arg_in, &type);
|
||||
|
||||
/* FIXME - handle container types */
|
||||
g_string_append_printf (xml, " <arg name=\"%s\" type=\"%s\" direction=\"%s\"/>\n",
|
||||
name, _dbus_gutils_type_to_string (type[0]), arg_in ? "in" : "out");
|
||||
|
||||
}
|
||||
g_string_append (xml, " </method>\n");
|
||||
}
|
||||
|
||||
g_string_append (xml, " </interface>\n");
|
||||
}
|
||||
|
||||
static void
|
||||
introspect_interfaces (GObject *object, GString *xml)
|
||||
{
|
||||
GType classtype;
|
||||
|
||||
g_static_rw_lock_reader_lock (&info_hash_lock);
|
||||
|
||||
for (classtype = G_TYPE_FROM_INSTANCE (object); classtype != 0; classtype = g_type_parent (classtype))
|
||||
{
|
||||
const DBusGObjectInfo *info;
|
||||
DBusGlibWriteIterfaceData data;
|
||||
|
||||
info = g_hash_table_lookup (info_hash,
|
||||
g_type_class_peek (classtype));
|
||||
|
||||
if (info != NULL && info->format_version == 0)
|
||||
{
|
||||
int i;
|
||||
GHashTable *interfaces;
|
||||
|
||||
/* Gather a list of all interfaces, indexed into their methods */
|
||||
interfaces = g_hash_table_new (g_str_hash, g_str_equal);
|
||||
for (i = 0; i < info->n_infos; i++)
|
||||
{
|
||||
const char *method_name;
|
||||
const char *method_interface;
|
||||
const char *method_args;
|
||||
const DBusGMethodInfo *method;
|
||||
GSList *methods;
|
||||
|
||||
method = &(info->infos[i]);
|
||||
|
||||
method_interface = method_interface_from_object_info (info, method);
|
||||
method_name = method_name_from_object_info (info, method);
|
||||
method_args = method_arg_info_from_object_info (info, method);
|
||||
|
||||
if ((methods = g_hash_table_lookup (interfaces, method_interface)) == NULL)
|
||||
methods = g_slist_prepend (NULL, (gpointer) method);
|
||||
else
|
||||
methods = g_slist_prepend (methods, (gpointer) method);
|
||||
g_hash_table_insert (interfaces, (gpointer) method_interface, methods);
|
||||
}
|
||||
|
||||
memset (&data, 0, sizeof (data));
|
||||
data.xml = xml;
|
||||
data.object_info = info;
|
||||
g_hash_table_foreach (interfaces, write_interface, &data);
|
||||
|
||||
g_hash_table_destroy (interfaces);
|
||||
}
|
||||
}
|
||||
|
||||
g_static_rw_lock_reader_lock (&info_hash_lock);
|
||||
}
|
||||
|
||||
static DBusHandlerResult
|
||||
handle_introspect (DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
|
|
@ -316,6 +557,7 @@ handle_introspect (DBusConnection *connection,
|
|||
|
||||
introspect_signals (G_OBJECT_TYPE (object), xml);
|
||||
introspect_properties (object, xml);
|
||||
introspect_interfaces (object, xml);
|
||||
|
||||
/* Append child nodes */
|
||||
for (i = 0; children[i]; i++)
|
||||
|
|
@ -392,7 +634,7 @@ get_object_property (DBusConnection *connection,
|
|||
GParamSpec *pspec)
|
||||
{
|
||||
GType value_type;
|
||||
GValue value;
|
||||
GValue value = {0, };
|
||||
DBusMessage *ret;
|
||||
DBusMessageIter iter;
|
||||
|
||||
|
|
@ -420,12 +662,275 @@ get_object_property (DBusConnection *connection,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
lookup_object_and_method (GObject *object,
|
||||
DBusMessage *message,
|
||||
const DBusGObjectInfo **object_ret,
|
||||
const DBusGMethodInfo **method_ret)
|
||||
{
|
||||
GType classtype;
|
||||
const char *interface;
|
||||
const char *member;
|
||||
const char *signature;
|
||||
gboolean ret;
|
||||
|
||||
interface = dbus_message_get_interface (message);
|
||||
member = dbus_message_get_member (message);
|
||||
signature = dbus_message_get_signature (message);
|
||||
ret = FALSE;
|
||||
|
||||
g_static_rw_lock_reader_lock (&info_hash_lock);
|
||||
|
||||
if (!info_hash)
|
||||
goto out;
|
||||
|
||||
for (classtype = G_TYPE_FROM_INSTANCE (object); classtype != 0; classtype = g_type_parent (classtype))
|
||||
{
|
||||
const DBusGObjectInfo *info;
|
||||
|
||||
info = g_hash_table_lookup (info_hash,
|
||||
g_type_class_peek (classtype));
|
||||
|
||||
*object_ret = info;
|
||||
|
||||
if (info != NULL && info->format_version == 0)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < info->n_infos; i++)
|
||||
{
|
||||
const char *expected_member;
|
||||
const char *expected_interface;
|
||||
char *expected_signature;
|
||||
const DBusGMethodInfo *method;
|
||||
|
||||
method = &(info->infos[i]);
|
||||
|
||||
/* Check method interface/name and input signature */
|
||||
expected_interface = method_interface_from_object_info (*object_ret, method);
|
||||
expected_member = method_name_from_object_info (*object_ret, method);
|
||||
expected_signature = method_input_signature_from_object_info (*object_ret, method);
|
||||
if ((interface == NULL
|
||||
|| strcmp (expected_interface, interface) == 0)
|
||||
&& strcmp (expected_member, member) == 0
|
||||
&& strcmp (expected_signature, signature) == 0)
|
||||
{
|
||||
g_free (expected_signature);
|
||||
*method_ret = method;
|
||||
ret = TRUE;
|
||||
goto out;
|
||||
}
|
||||
g_free (expected_signature);
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
g_static_rw_lock_reader_lock (&info_hash_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *
|
||||
gerror_domaincode_to_dbus_error_name (const DBusGObjectInfo *object_info,
|
||||
GQuark domain, gint code)
|
||||
{
|
||||
const char *domain_str;
|
||||
const char *code_str;
|
||||
GString *dbus_error_name;
|
||||
|
||||
domain_str = object_error_domain_prefix_from_object_info (object_info);
|
||||
code_str = object_error_code_from_object_info (object_info, domain, code);
|
||||
|
||||
if (!domain_str || !code_str)
|
||||
{
|
||||
/* If we can't map it sensibly, make up an error name */
|
||||
char *domain_from_quark;
|
||||
|
||||
dbus_error_name = g_string_new ("org.freedesktop.DBus.GLib.UnmappedError.");
|
||||
|
||||
domain_from_quark = uscore_to_wincaps (g_quark_to_string (domain));
|
||||
g_string_append (dbus_error_name, domain_from_quark);
|
||||
g_free (domain_from_quark);
|
||||
|
||||
g_string_append_printf (dbus_error_name, ".Code%d", code);
|
||||
}
|
||||
else
|
||||
{
|
||||
dbus_error_name = g_string_new (domain_str);
|
||||
g_string_append_c (dbus_error_name, '.');
|
||||
g_string_append (dbus_error_name, code_str);
|
||||
}
|
||||
|
||||
return g_string_free (dbus_error_name, FALSE);
|
||||
}
|
||||
|
||||
static DBusMessage *
|
||||
gerror_to_dbus_error_message (const DBusGObjectInfo *object_info,
|
||||
DBusMessage *message,
|
||||
GError *error)
|
||||
{
|
||||
DBusMessage *reply;
|
||||
|
||||
if (!error)
|
||||
{
|
||||
char *error_msg;
|
||||
|
||||
error_msg = g_strdup_printf ("Method invoked for %s returned FALSE but did not set error", dbus_message_get_member (message));
|
||||
reply = dbus_message_new_error (message, "org.freedesktop.DBus.GLib.ErrorError", error_msg);
|
||||
g_free (error_msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *error_name;
|
||||
error_name = gerror_domaincode_to_dbus_error_name (object_info, error->domain, error->code);
|
||||
reply = dbus_message_new_error (message, error_name, error->message);
|
||||
g_free (error_name);
|
||||
}
|
||||
return reply;
|
||||
}
|
||||
|
||||
static DBusHandlerResult
|
||||
invoke_object_method (GObject *object,
|
||||
const DBusGObjectInfo *object_info,
|
||||
const DBusGMethodInfo *method,
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message)
|
||||
{
|
||||
gboolean had_error;
|
||||
GError *gerror;
|
||||
GValueArray *value_array;
|
||||
GValue object_value = {0,};
|
||||
GValue error_value = {0,};
|
||||
GValue return_value = {0,};
|
||||
GClosure closure;
|
||||
char *out_signature;
|
||||
int out_signature_len;
|
||||
GArray *out_param_values;
|
||||
int i;
|
||||
DBusHandlerResult result;
|
||||
DBusMessage *reply;
|
||||
|
||||
gerror = NULL;
|
||||
|
||||
/* This is evil. We do this to work around the fact that
|
||||
* the generated glib marshallers check a flag in the closure object
|
||||
* which we don't care about. We don't need/want to create
|
||||
* a new closure for each invocation.
|
||||
*/
|
||||
memset (&closure, 0, sizeof (closure));
|
||||
|
||||
/* Convert method IN parameters to GValueArray */
|
||||
value_array = dbus_glib_marshal_dbus_message_to_gvalue_array (message);
|
||||
|
||||
g_return_val_if_fail (value_array != NULL, DBUS_HANDLER_RESULT_NOT_YET_HANDLED);
|
||||
|
||||
/* Prepend object as first argument */
|
||||
g_value_init (&object_value, G_TYPE_OBJECT);
|
||||
g_value_set_object (&object_value, object);
|
||||
g_value_array_prepend (value_array, &object_value);
|
||||
|
||||
out_signature = method_output_signature_from_object_info (object_info, method);
|
||||
out_signature_len = strlen (out_signature);
|
||||
|
||||
/* Create an array to store the actual values of OUT
|
||||
* parameters. Then, create a GValue boxed POINTER
|
||||
* to each of those values, and append to the invocation,
|
||||
* so the method can return the OUT parameters.
|
||||
*/
|
||||
out_param_values = g_array_new (FALSE, TRUE, sizeof (DBusBasicGValue));
|
||||
for (i = 0; i < out_signature_len; i++)
|
||||
{
|
||||
GValue value = {0, };
|
||||
DBusBasicGValue basic;
|
||||
|
||||
memset (&basic, 0, sizeof (basic));
|
||||
|
||||
/* FIXME - broken for container types */
|
||||
|
||||
g_array_append_val (out_param_values, basic);
|
||||
g_value_init (&value, G_TYPE_POINTER);
|
||||
g_value_set_pointer (&value, &(g_array_index (out_param_values, DBusBasicGValue, i)));
|
||||
g_value_array_append (value_array, &value);
|
||||
}
|
||||
|
||||
/* Append GError as final argument */
|
||||
g_value_init (&error_value, G_TYPE_POINTER);
|
||||
g_value_set_pointer (&error_value, &gerror);
|
||||
g_value_array_append (value_array, &error_value);
|
||||
|
||||
/* Actually invoke method */
|
||||
g_value_init (&return_value, G_TYPE_BOOLEAN);
|
||||
method->marshaller (&closure, &return_value,
|
||||
value_array->n_values,
|
||||
value_array->values,
|
||||
NULL, method->function);
|
||||
had_error = !g_value_get_boolean (&return_value);
|
||||
|
||||
if (!had_error)
|
||||
{
|
||||
DBusMessageIter iter;
|
||||
|
||||
reply = dbus_message_new_method_return (message);
|
||||
if (reply == NULL)
|
||||
goto nomem;
|
||||
|
||||
/* Append OUT arguments to reply */
|
||||
dbus_message_iter_init_append (reply, &iter);
|
||||
for (i = 0; i < out_signature_len; i++)
|
||||
{
|
||||
DBusBasicGValue *value;
|
||||
|
||||
/* FIXME - broken for container types */
|
||||
|
||||
value = &(g_array_index (out_param_values, DBusBasicGValue, i));
|
||||
if (!dbus_message_iter_append_basic (&iter, out_signature[i], value))
|
||||
goto nomem;
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
reply = gerror_to_dbus_error_message (object_info, message, gerror);
|
||||
|
||||
if (reply)
|
||||
{
|
||||
dbus_connection_send (connection, reply, NULL);
|
||||
dbus_message_unref (reply);
|
||||
}
|
||||
|
||||
/* Assume that if there was an error, no return values are
|
||||
* set */
|
||||
if (!had_error)
|
||||
{
|
||||
/* Be sure to free all returned STRING arguments for now;
|
||||
* later this should be specified via method info parameter
|
||||
* annotation; probably we want to support custom free funcs too */
|
||||
for (i = 0; i < out_signature_len; i++)
|
||||
{
|
||||
DBusBasicGValue *value;
|
||||
|
||||
value = &(g_array_index (out_param_values, DBusBasicGValue, i));
|
||||
if (out_signature[i] == DBUS_TYPE_STRING)
|
||||
g_free (value->gpointer_val);
|
||||
}
|
||||
}
|
||||
|
||||
result = DBUS_HANDLER_RESULT_HANDLED;
|
||||
done:
|
||||
g_free (out_signature);
|
||||
g_array_free (out_param_values, TRUE);
|
||||
g_value_array_free (value_array);
|
||||
g_value_unset (&object_value);
|
||||
g_value_unset (&error_value);
|
||||
g_value_unset (&return_value);
|
||||
return result;
|
||||
nomem:
|
||||
result = DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
static DBusHandlerResult
|
||||
gobject_message_function (DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
void *user_data)
|
||||
{
|
||||
const DBusGObjectInfo *info;
|
||||
GParamSpec *pspec;
|
||||
GObject *object;
|
||||
gboolean setter;
|
||||
|
|
@ -434,6 +939,8 @@ gobject_message_function (DBusConnection *connection,
|
|||
const char *wincaps_propname;
|
||||
/* const char *wincaps_propiface; */
|
||||
DBusMessageIter iter;
|
||||
const DBusGMethodInfo *method;
|
||||
const DBusGObjectInfo *object_info;
|
||||
|
||||
object = G_OBJECT (user_data);
|
||||
|
||||
|
|
@ -441,23 +948,10 @@ gobject_message_function (DBusConnection *connection,
|
|||
DBUS_INTERFACE_ORG_FREEDESKTOP_INTROSPECTABLE,
|
||||
"Introspect"))
|
||||
return handle_introspect (connection, message, object);
|
||||
|
||||
|
||||
/* Try the metainfo, which lets us invoke methods */
|
||||
|
||||
g_static_mutex_lock (&info_hash_mutex);
|
||||
/* FIXME this needs to walk up the inheritance tree, not
|
||||
* just look at the most-derived class
|
||||
*/
|
||||
info = g_hash_table_lookup (info_hash,
|
||||
G_OBJECT_GET_CLASS (object));
|
||||
g_static_mutex_unlock (&info_hash_mutex);
|
||||
|
||||
if (info != NULL)
|
||||
{
|
||||
|
||||
|
||||
|
||||
}
|
||||
if (lookup_object_and_method (object, message, &object_info, &method))
|
||||
return invoke_object_method (object, object_info, method, connection, message);
|
||||
|
||||
/* If no metainfo, we can still do properties and signals
|
||||
* via standard GLib introspection
|
||||
|
|
@ -497,7 +991,7 @@ gobject_message_function (DBusConnection *connection,
|
|||
dbus_message_iter_get_basic (&iter, &wincaps_propname);
|
||||
dbus_message_iter_next (&iter);
|
||||
|
||||
s = wincaps_to_uscore (wincaps_propname);
|
||||
s = _dbus_gutils_wincaps_to_uscore (wincaps_propname);
|
||||
|
||||
pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object),
|
||||
s);
|
||||
|
|
@ -577,7 +1071,7 @@ dbus_g_object_class_install_info (GObjectClass *object_class,
|
|||
{
|
||||
g_return_if_fail (G_IS_OBJECT_CLASS (object_class));
|
||||
|
||||
g_static_mutex_lock (&info_hash_mutex);
|
||||
g_static_rw_lock_writer_lock (&info_hash_lock);
|
||||
|
||||
if (info_hash == NULL)
|
||||
{
|
||||
|
|
@ -586,7 +1080,7 @@ dbus_g_object_class_install_info (GObjectClass *object_class,
|
|||
|
||||
g_hash_table_replace (info_hash, object_class, (void*) info);
|
||||
|
||||
g_static_mutex_unlock (&info_hash_mutex);
|
||||
g_static_rw_lock_writer_unlock (&info_hash_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -652,7 +1146,7 @@ _dbus_gobject_test (const char *test_data_dir)
|
|||
char *uscore;
|
||||
char *wincaps;
|
||||
|
||||
uscore = wincaps_to_uscore (name_pairs[i].wincaps);
|
||||
uscore = _dbus_gutils_wincaps_to_uscore (name_pairs[i].wincaps);
|
||||
wincaps = uscore_to_wincaps (name_pairs[i].uscore);
|
||||
|
||||
if (strcmp (uscore, name_pairs[i].uscore) != 0)
|
||||
|
|
|
|||
35
glib/dbus-gobject.h
Normal file
35
glib/dbus-gobject.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/* -*- mode: C; c-file-style: "gnu" -*- */
|
||||
/* dbus-gobject.h: common functions used to map between D-BUS and GObject
|
||||
*
|
||||
* Copyright (C) 2005 Red Hat, Inc.
|
||||
*
|
||||
* Licensed under the Academic Free License version 2.1
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
#ifndef DBUS_GLIB_OBJECT_H
|
||||
#define DBUS_GLIB_OBJECT_H
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
#include <glib.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GValueArray* dbus_glib_marshal_dbus_message_to_gvalue_array (DBusMessage *message);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
|
@ -308,6 +308,7 @@ parse_interface (Parser *parser,
|
|||
GError **error)
|
||||
{
|
||||
const char *name;
|
||||
const char *c_name;
|
||||
InterfaceInfo *iface;
|
||||
NodeInfo *top;
|
||||
|
||||
|
|
@ -329,6 +330,7 @@ parse_interface (Parser *parser,
|
|||
if (!locate_attributes (element_name, attribute_names,
|
||||
attribute_values, error,
|
||||
"name", &name,
|
||||
"c_name", &c_name,
|
||||
NULL))
|
||||
return FALSE;
|
||||
|
||||
|
|
@ -344,6 +346,8 @@ parse_interface (Parser *parser,
|
|||
top = parser->node_stack->data;
|
||||
|
||||
iface = interface_info_new (name);
|
||||
if (c_name)
|
||||
interface_info_set_binding_name (iface, "C", c_name);
|
||||
node_info_add_interface (top, iface);
|
||||
interface_info_unref (iface);
|
||||
|
||||
|
|
@ -360,6 +364,7 @@ parse_method (Parser *parser,
|
|||
GError **error)
|
||||
{
|
||||
const char *name;
|
||||
const char *c_name;
|
||||
MethodInfo *method;
|
||||
NodeInfo *top;
|
||||
|
||||
|
|
@ -381,6 +386,7 @@ parse_method (Parser *parser,
|
|||
if (!locate_attributes (element_name, attribute_names,
|
||||
attribute_values, error,
|
||||
"name", &name,
|
||||
"c_name", &c_name,
|
||||
NULL))
|
||||
return FALSE;
|
||||
|
||||
|
|
@ -396,6 +402,8 @@ parse_method (Parser *parser,
|
|||
top = parser->node_stack->data;
|
||||
|
||||
method = method_info_new (name);
|
||||
if (c_name)
|
||||
method_info_set_binding_name (method, "C", c_name);
|
||||
interface_info_add_method (parser->interface, method);
|
||||
method_info_unref (method);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
#include "dbus-gutils.h"
|
||||
#include "dbus-gmarshal.h"
|
||||
#include "dbus-gvalue.h"
|
||||
#include "dbus-gobject.h"
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
|
|
@ -900,11 +901,8 @@ marshal_dbus_message_to_g_marshaller (GClosure *closure,
|
|||
* marshaller.
|
||||
*/
|
||||
#define MAX_SIGNATURE_ARGS 20
|
||||
GValue expanded[MAX_SIGNATURE_ARGS];
|
||||
int arg;
|
||||
int i;
|
||||
DBusMessageIter iter;
|
||||
int dtype;
|
||||
GValueArray *value_array;
|
||||
GValue value = {0, };
|
||||
GSignalCMarshaller c_marshaller;
|
||||
DBusGProxy *proxy;
|
||||
DBusMessage *message;
|
||||
|
|
@ -924,44 +922,18 @@ marshal_dbus_message_to_g_marshaller (GClosure *closure,
|
|||
|
||||
g_return_if_fail (c_marshaller != NULL);
|
||||
|
||||
memset (&expanded[0], 0, sizeof (expanded));
|
||||
|
||||
arg = 0;
|
||||
|
||||
g_value_init (&expanded[arg], G_TYPE_FROM_INSTANCE (proxy));
|
||||
g_value_set_instance (&expanded[arg], proxy);
|
||||
++arg;
|
||||
|
||||
dbus_message_iter_init (message, &iter);
|
||||
|
||||
while ((dtype = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
|
||||
{
|
||||
if (arg == MAX_SIGNATURE_ARGS)
|
||||
{
|
||||
g_warning ("Don't support more than %d signal args\n", MAX_SIGNATURE_ARGS);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!dbus_gvalue_demarshal (&iter, &expanded[arg]))
|
||||
{
|
||||
g_warning ("Unable to convert arg type %d to GValue to emit DBusGProxy signal", dtype);
|
||||
goto out;
|
||||
}
|
||||
|
||||
++arg;
|
||||
dbus_message_iter_next (&iter);
|
||||
}
|
||||
value_array = dbus_glib_marshal_dbus_message_to_gvalue_array (message);
|
||||
|
||||
(* c_marshaller) (closure, return_value, arg, &expanded[0],
|
||||
invocation_hint, marshal_data);
|
||||
g_return_if_fail (value_array != NULL);
|
||||
|
||||
out:
|
||||
i = 0;
|
||||
while (i < arg)
|
||||
{
|
||||
g_value_unset (&expanded[i]);
|
||||
++i;
|
||||
}
|
||||
g_value_init (&value, G_TYPE_FROM_INSTANCE (proxy));
|
||||
g_value_set_instance (&value, proxy);
|
||||
g_value_array_prepend (value_array, &value);
|
||||
|
||||
(* c_marshaller) (closure, return_value, value_array->n_values,
|
||||
value_array->values, invocation_hint, marshal_data);
|
||||
|
||||
g_value_array_free (value_array);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -125,6 +125,34 @@ _dbus_gutils_type_to_string (int type)
|
|||
}
|
||||
}
|
||||
|
||||
char*
|
||||
_dbus_gutils_wincaps_to_uscore (const char *caps)
|
||||
{
|
||||
const char *p;
|
||||
GString *str;
|
||||
|
||||
str = g_string_new (NULL);
|
||||
p = caps;
|
||||
while (*p)
|
||||
{
|
||||
if (g_ascii_isupper (*p))
|
||||
{
|
||||
if (str->len > 0 &&
|
||||
(str->len < 2 || str->str[str->len-2] != '_'))
|
||||
g_string_append_c (str, '_');
|
||||
g_string_append_c (str, g_ascii_tolower (*p));
|
||||
}
|
||||
else
|
||||
{
|
||||
g_string_append_c (str, *p);
|
||||
}
|
||||
++p;
|
||||
}
|
||||
|
||||
return g_string_free (str, FALSE);
|
||||
}
|
||||
|
||||
|
||||
#ifdef DBUS_BUILD_TESTS
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ G_BEGIN_DECLS
|
|||
char **_dbus_gutils_split_path (const char *path);
|
||||
const char *_dbus_gutils_type_to_string (int type);
|
||||
|
||||
char *_dbus_gutils_wincaps_to_uscore (const char *uscore);
|
||||
|
||||
/* These munge the pointer to enforce that a plain cast won't work,
|
||||
* accessor functions must be used; i.e. to ensure the ABI
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
/* dbus-gvalue.c GValue to-from DBusMessageIter
|
||||
*
|
||||
* Copyright (C) 2004 Ximian, Inc.
|
||||
* Copyright (C) 2005 Red Hat, Inc.
|
||||
*
|
||||
* Licensed under the Academic Free License version 2.1
|
||||
*
|
||||
|
|
@ -23,20 +24,178 @@
|
|||
|
||||
#include <dbus-gvalue.h>
|
||||
|
||||
/* This is slightly evil, we don't use g_value_set_foo() functions */
|
||||
#define MAP_BASIC_INIT(d_t, g_t) \
|
||||
case DBUS_TYPE_##d_t: \
|
||||
g_value_init (value, G_TYPE_##g_t); \
|
||||
break
|
||||
|
||||
gboolean
|
||||
dbus_gvalue_init (int type,
|
||||
GValue *value)
|
||||
{
|
||||
gboolean can_convert;
|
||||
|
||||
can_convert = TRUE;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
MAP_BASIC_INIT (BOOLEAN, BOOLEAN);
|
||||
MAP_BASIC_INIT (BYTE, UCHAR);
|
||||
MAP_BASIC_INIT (INT32, INT);
|
||||
MAP_BASIC_INIT (UINT32, UINT);
|
||||
MAP_BASIC_INIT (INT64, INT64);
|
||||
MAP_BASIC_INIT (UINT64, UINT64);
|
||||
MAP_BASIC_INIT (DOUBLE, DOUBLE);
|
||||
|
||||
case DBUS_TYPE_INT16:
|
||||
g_value_init (value, G_TYPE_INT);
|
||||
break;
|
||||
case DBUS_TYPE_UINT16:
|
||||
g_value_init (value, G_TYPE_UINT);
|
||||
break;
|
||||
|
||||
case DBUS_TYPE_STRING:
|
||||
case DBUS_TYPE_OBJECT_PATH:
|
||||
case DBUS_TYPE_SIGNATURE:
|
||||
g_value_init (value, G_TYPE_STRING);
|
||||
break;
|
||||
|
||||
case DBUS_TYPE_STRUCT:
|
||||
case DBUS_TYPE_ARRAY:
|
||||
case DBUS_TYPE_VARIANT:
|
||||
default:
|
||||
can_convert = FALSE;
|
||||
}
|
||||
#undef MAP_BASIC_INIT
|
||||
return can_convert;
|
||||
}
|
||||
|
||||
const char *
|
||||
dbus_gvalue_genmarshal_name_from_type (int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DBUS_TYPE_BOOLEAN:
|
||||
return "BOOLEAN";
|
||||
case DBUS_TYPE_BYTE:
|
||||
return "UCHAR";
|
||||
case DBUS_TYPE_INT32:
|
||||
return "INT";
|
||||
case DBUS_TYPE_UINT32:
|
||||
return "UINT";
|
||||
case DBUS_TYPE_INT64:
|
||||
return "INT64";
|
||||
case DBUS_TYPE_UINT64:
|
||||
return "UINT64";
|
||||
case DBUS_TYPE_DOUBLE:
|
||||
return "DOUBLE";
|
||||
case DBUS_TYPE_INT16:
|
||||
return "INT";
|
||||
break;
|
||||
case DBUS_TYPE_UINT16:
|
||||
return "UINT";
|
||||
case DBUS_TYPE_STRING:
|
||||
case DBUS_TYPE_OBJECT_PATH:
|
||||
case DBUS_TYPE_SIGNATURE:
|
||||
return "STRING";
|
||||
|
||||
case DBUS_TYPE_STRUCT:
|
||||
case DBUS_TYPE_ARRAY:
|
||||
case DBUS_TYPE_VARIANT:
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
dbus_gvalue_binding_type_from_type (int type)
|
||||
{
|
||||
#define STRINGIFY(x) \
|
||||
case x: \
|
||||
return (#x)
|
||||
|
||||
switch (type)
|
||||
{
|
||||
STRINGIFY(DBUS_TYPE_BOOLEAN);
|
||||
STRINGIFY(DBUS_TYPE_BYTE);
|
||||
STRINGIFY(DBUS_TYPE_INT32);
|
||||
STRINGIFY(DBUS_TYPE_UINT32);
|
||||
STRINGIFY(DBUS_TYPE_INT64);
|
||||
STRINGIFY(DBUS_TYPE_UINT64);
|
||||
STRINGIFY(DBUS_TYPE_DOUBLE);
|
||||
case DBUS_TYPE_INT16:
|
||||
return "DBUS_TYPE_INT32";
|
||||
case DBUS_TYPE_UINT16:
|
||||
return "DBUS_TYPE_UINT32";
|
||||
STRINGIFY(DBUS_TYPE_STRING);
|
||||
STRINGIFY(DBUS_TYPE_OBJECT_PATH);
|
||||
STRINGIFY(DBUS_TYPE_SIGNATURE);
|
||||
|
||||
case DBUS_TYPE_STRUCT:
|
||||
case DBUS_TYPE_ARRAY:
|
||||
case DBUS_TYPE_VARIANT:
|
||||
return NULL;
|
||||
}
|
||||
#undef STRINGIFY
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *
|
||||
dbus_gvalue_ctype_from_type (int type, gboolean in)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DBUS_TYPE_BOOLEAN:
|
||||
return "gboolean";
|
||||
case DBUS_TYPE_BYTE:
|
||||
return "guchar";
|
||||
case DBUS_TYPE_INT32:
|
||||
return "gint32";
|
||||
case DBUS_TYPE_UINT32:
|
||||
return "guint32";
|
||||
case DBUS_TYPE_INT64:
|
||||
return "gint64";
|
||||
case DBUS_TYPE_UINT64:
|
||||
return "guint64";
|
||||
case DBUS_TYPE_DOUBLE:
|
||||
return "gdouble";
|
||||
case DBUS_TYPE_INT16:
|
||||
return "gint";
|
||||
break;
|
||||
case DBUS_TYPE_UINT16:
|
||||
return "guint";
|
||||
case DBUS_TYPE_STRING:
|
||||
case DBUS_TYPE_OBJECT_PATH:
|
||||
case DBUS_TYPE_SIGNATURE:
|
||||
/* FIXME - kind of a hack */
|
||||
if (in)
|
||||
return "const char *";
|
||||
else
|
||||
return "char *";
|
||||
case DBUS_TYPE_STRUCT:
|
||||
case DBUS_TYPE_ARRAY:
|
||||
case DBUS_TYPE_VARIANT:
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
dbus_gvalue_demarshal (DBusMessageIter *iter, GValue *value)
|
||||
{
|
||||
gboolean can_convert = TRUE;
|
||||
|
||||
/* This is slightly evil, we don't use g_value_set_foo() functions */
|
||||
g_assert (sizeof (dbus_bool_t) == sizeof (value->data[0].v_int));
|
||||
|
||||
dbus_gvalue_init (dbus_message_iter_get_arg_type (iter), value);
|
||||
|
||||
/* This is slightly evil, we don't use g_value_set_foo() functions */
|
||||
#define MAP_BASIC(d_t, g_t) \
|
||||
case DBUS_TYPE_##d_t: \
|
||||
g_value_init (value, G_TYPE_##g_t); \
|
||||
dbus_message_iter_get_basic (iter, &value->data[0]); \
|
||||
break
|
||||
|
||||
g_assert (sizeof (dbus_bool_t) == sizeof (value->data[0].v_int));
|
||||
|
||||
switch (dbus_message_iter_get_arg_type (iter))
|
||||
{
|
||||
MAP_BASIC (BOOLEAN, BOOLEAN);
|
||||
|
|
@ -50,7 +209,6 @@ dbus_gvalue_demarshal (DBusMessageIter *iter, GValue *value)
|
|||
case DBUS_TYPE_INT16:
|
||||
{
|
||||
dbus_int16_t v;
|
||||
g_value_init (value, G_TYPE_INT);
|
||||
dbus_message_iter_get_basic (iter, &v);
|
||||
g_value_set_int (value, v);
|
||||
}
|
||||
|
|
@ -58,7 +216,6 @@ dbus_gvalue_demarshal (DBusMessageIter *iter, GValue *value)
|
|||
case DBUS_TYPE_UINT16:
|
||||
{
|
||||
dbus_uint16_t v;
|
||||
g_value_init (value, G_TYPE_UINT);
|
||||
dbus_message_iter_get_basic (iter, &v);
|
||||
g_value_set_uint (value, v);
|
||||
}
|
||||
|
|
@ -70,8 +227,6 @@ dbus_gvalue_demarshal (DBusMessageIter *iter, GValue *value)
|
|||
{
|
||||
const char *s;
|
||||
|
||||
g_value_init (value, G_TYPE_STRING);
|
||||
|
||||
dbus_message_iter_get_basic (iter, &s);
|
||||
g_value_set_string (value, s);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,32 @@
|
|||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
gboolean dbus_gvalue_demarshal (DBusMessageIter *iter, GValue *value);
|
||||
gboolean dbus_gvalue_marshal (DBusMessageIter *iter, GValue *value);
|
||||
/* Used for return value storage */
|
||||
typedef union
|
||||
{
|
||||
gboolean gboolean_val;
|
||||
guchar guchar_val;
|
||||
gint int_val;
|
||||
gint64 gint64_val;
|
||||
guint64 guint64_val;
|
||||
double double_val;
|
||||
gpointer gpointer_val;
|
||||
char * chararray_val;
|
||||
} DBusBasicGValue;
|
||||
|
||||
const char * dbus_gvalue_genmarshal_name_from_type (int type);
|
||||
|
||||
const char * dbus_gvalue_ctype_from_type (int type, gboolean in);
|
||||
|
||||
const char * dbus_gvalue_binding_type_from_type (int type);
|
||||
|
||||
gboolean dbus_gvalue_init (int type,
|
||||
GValue *value);
|
||||
|
||||
gboolean dbus_gvalue_demarshal (DBusMessageIter *iter,
|
||||
GValue *value);
|
||||
gboolean dbus_gvalue_marshal (DBusMessageIter *iter,
|
||||
GValue *value);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
|||
|
|
@ -40,7 +40,20 @@ test_dbus_glib_SOURCES= \
|
|||
test_dbus_glib_LDADD= $(top_builddir)/glib/libdbus-glib-1.la
|
||||
|
||||
test_service_glib_SOURCES= \
|
||||
test-service-glib.c
|
||||
test-service-glib.c \
|
||||
test-service-glib-glue.h
|
||||
|
||||
BUILT_SOURCES = test-service-glib-glue.h test-service-glib-bindings.h
|
||||
|
||||
test-service-glib-glue.h: $(top_builddir)/glib/dbus-binding-tool test-service-glib.xml
|
||||
$(top_builddir)/glib/dbus-binding-tool --mode=glib-server $(srcdir)/test-service-glib.xml > test-service-glib-glue.h.tmp
|
||||
mv test-service-glib-glue.h.tmp test-service-glib-glue.h
|
||||
|
||||
test-service-glib-bindings.h: $(top_builddir)/glib/dbus-binding-tool test-service-glib.xml
|
||||
$(top_builddir)/glib/dbus-binding-tool --mode=glib-client $(srcdir)/test-service-glib.xml > test-service-glib-bindings.h.tmp
|
||||
mv test-service-glib-bindings.h.tmp test-service-glib-bindings.h
|
||||
|
||||
CLEANFILES = test-service-glib-glue.h test-service-glib-glue.h.tmp test-service-glib-bindings.h test-service-glib-bindings.h.tmp
|
||||
|
||||
test_service_glib_LDADD= $(top_builddir)/glib/libdbus-glib-1.la
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "test-service-glib-bindings.h"
|
||||
|
||||
static GMainLoop *loop = NULL;
|
||||
static int n_times_foo_received = 0;
|
||||
|
|
@ -37,7 +38,11 @@ main (int argc, char **argv)
|
|||
int i;
|
||||
guint32 result;
|
||||
const char *v_STRING;
|
||||
char *v_STRING_2;
|
||||
guint32 v_UINT32;
|
||||
guint32 v_UINT32_2;
|
||||
double v_DOUBLE;
|
||||
double v_DOUBLE_2;
|
||||
|
||||
g_type_init ();
|
||||
|
||||
|
|
@ -220,10 +225,204 @@ main (int argc, char **argv)
|
|||
n_times_foo_received);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
g_object_unref (G_OBJECT (driver));
|
||||
|
||||
/* Activate test servie */
|
||||
g_print ("Activating TestSuiteGLibService\n");
|
||||
v_STRING = "org.freedesktop.DBus.TestSuiteGLibService";
|
||||
v_UINT32 = 0;
|
||||
call = dbus_g_proxy_begin_call (driver, "StartServiceByName",
|
||||
DBUS_TYPE_STRING,
|
||||
&v_STRING,
|
||||
DBUS_TYPE_UINT32,
|
||||
&v_UINT32,
|
||||
DBUS_TYPE_INVALID);
|
||||
|
||||
error = NULL;
|
||||
if (!dbus_g_proxy_end_call (driver, call, &error,
|
||||
DBUS_TYPE_UINT32, &result,
|
||||
DBUS_TYPE_INVALID))
|
||||
{
|
||||
g_printerr ("Failed to complete Activate call: %s\n",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
g_object_unref (G_OBJECT (proxy));
|
||||
|
||||
proxy = dbus_g_proxy_new_for_name_owner (connection,
|
||||
"org.freedesktop.DBus.TestSuiteGLibService",
|
||||
"/org/freedesktop/DBus/Tests/MyTestObject",
|
||||
"org.freedesktop.DBus.Tests.MyObject",
|
||||
&error);
|
||||
|
||||
if (proxy == NULL)
|
||||
{
|
||||
g_printerr ("Failed to create proxy for name owner: %s\n",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
call = dbus_g_proxy_begin_call (proxy, "DoNothing",
|
||||
DBUS_TYPE_INVALID);
|
||||
error = NULL;
|
||||
if (!dbus_g_proxy_end_call (proxy, call, &error, DBUS_TYPE_INVALID))
|
||||
{
|
||||
g_printerr ("Failed to complete DoNothing call: %s\n",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
v_UINT32 = 42;
|
||||
call = dbus_g_proxy_begin_call (proxy, "Increment",
|
||||
DBUS_TYPE_UINT32, &v_UINT32,
|
||||
DBUS_TYPE_INVALID);
|
||||
error = NULL;
|
||||
if (!dbus_g_proxy_end_call (proxy, call, &error,
|
||||
DBUS_TYPE_UINT32, &v_UINT32_2,
|
||||
DBUS_TYPE_INVALID))
|
||||
{
|
||||
g_printerr ("Failed to complete Increment call: %s\n",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (v_UINT32_2 != v_UINT32 + 1)
|
||||
{
|
||||
g_printerr ("Increment call returned %d, should be 43\n", v_UINT32_2);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
call = dbus_g_proxy_begin_call (proxy, "ThrowError", DBUS_TYPE_INVALID);
|
||||
error = NULL;
|
||||
if (dbus_g_proxy_end_call (proxy, call, &error, DBUS_TYPE_INVALID) != FALSE)
|
||||
{
|
||||
g_printerr ("ThrowError call unexpectedly succeeded!\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
g_print ("ThrowError failed (as expected) returned error: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
|
||||
v_STRING = "foobar";
|
||||
call = dbus_g_proxy_begin_call (proxy, "Uppercase",
|
||||
DBUS_TYPE_STRING, &v_STRING,
|
||||
DBUS_TYPE_INVALID);
|
||||
error = NULL;
|
||||
if (!dbus_g_proxy_end_call (proxy, call, &error,
|
||||
DBUS_TYPE_STRING, &v_STRING_2,
|
||||
DBUS_TYPE_INVALID))
|
||||
{
|
||||
g_printerr ("Failed to complete Uppercase call: %s\n",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
exit (1);
|
||||
}
|
||||
if (strcmp ("FOOBAR", v_STRING_2) != 0)
|
||||
{
|
||||
g_printerr ("Uppercase call returned unexpected string %s\n", v_STRING_2);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
v_STRING = "bazwhee";
|
||||
v_UINT32 = 26;
|
||||
v_DOUBLE = G_PI;
|
||||
call = dbus_g_proxy_begin_call (proxy, "ManyArgs",
|
||||
DBUS_TYPE_UINT32, &v_UINT32,
|
||||
DBUS_TYPE_STRING, &v_STRING,
|
||||
DBUS_TYPE_DOUBLE, &v_DOUBLE,
|
||||
DBUS_TYPE_INVALID);
|
||||
error = NULL;
|
||||
if (!dbus_g_proxy_end_call (proxy, call, &error,
|
||||
DBUS_TYPE_DOUBLE, &v_DOUBLE_2,
|
||||
DBUS_TYPE_STRING, &v_STRING_2,
|
||||
DBUS_TYPE_INVALID))
|
||||
{
|
||||
g_printerr ("Failed to complete ManyArgs call: %s\n",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
exit (1);
|
||||
}
|
||||
if (v_DOUBLE_2 < 55 || v_DOUBLE_2 > 56)
|
||||
{
|
||||
g_printerr ("ManyArgs call returned unexpected double value %f\n", v_DOUBLE_2);
|
||||
exit (1);
|
||||
}
|
||||
if (strcmp ("BAZWHEE", v_STRING_2) != 0)
|
||||
{
|
||||
g_printerr ("ManyArgs call returned unexpected string %s\n", v_STRING_2);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (!org_freedesktop_DBus_Tests_MyObject_do_nothing (proxy, &error))
|
||||
{
|
||||
g_printerr ("Failed to complete (wrapped) DoNothing call: %s\n",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (!org_freedesktop_DBus_Tests_MyObject_increment (proxy, 42, &v_UINT32_2, &error))
|
||||
{
|
||||
g_printerr ("Failed to complete (wrapped) Increment call: %s\n",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (v_UINT32_2 != 43)
|
||||
{
|
||||
g_printerr ("(wrapped) increment call returned %d, should be 43\n", v_UINT32_2);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (org_freedesktop_DBus_Tests_MyObject_throw_error (proxy, &error) != FALSE)
|
||||
{
|
||||
g_printerr ("(wrapped) ThrowError call unexpectedly succeeded!\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
g_print ("(wrapped) ThrowError failed (as expected) returned error: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
|
||||
if (!org_freedesktop_DBus_Tests_MyObject_uppercase (proxy, "foobar", &v_STRING_2, &error))
|
||||
{
|
||||
g_printerr ("Failed to complete (wrapped) Uppercase call: %s\n",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
exit (1);
|
||||
}
|
||||
if (strcmp ("FOOBAR", v_STRING_2) != 0)
|
||||
{
|
||||
g_printerr ("(wrapped) Uppercase call returned unexpected string %s\n", v_STRING_2);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (!org_freedesktop_DBus_Tests_MyObject_many_args (proxy, 26, "bazwhee", G_PI,
|
||||
&v_DOUBLE_2, &v_STRING_2, &error))
|
||||
{
|
||||
g_printerr ("Failed to complete (wrapped) ManyArgs call: %s\n",
|
||||
error->message);
|
||||
g_error_free (error);
|
||||
exit (1);
|
||||
}
|
||||
if (v_DOUBLE_2 < 55 || v_DOUBLE_2 > 56)
|
||||
{
|
||||
g_printerr ("(wrapped) ManyArgs call returned unexpected double value %f\n", v_DOUBLE_2);
|
||||
exit (1);
|
||||
}
|
||||
if (strcmp ("BAZWHEE", v_STRING_2) != 0)
|
||||
{
|
||||
g_printerr ("(wrapped) ManyArgs call returned unexpected string %s\n", v_STRING_2);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
g_object_unref (G_OBJECT (proxy));
|
||||
g_object_unref (G_OBJECT (driver));
|
||||
|
||||
g_print ("Successfully completed %s\n", argv[0]);
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib-object.h>
|
||||
#include <glib/gquark.h>
|
||||
|
||||
typedef struct MyObject MyObject;
|
||||
typedef struct MyObjectClass MyObjectClass;
|
||||
|
|
@ -30,6 +32,28 @@ struct MyObjectClass
|
|||
|
||||
G_DEFINE_TYPE(MyObject, my_object, G_TYPE_OBJECT)
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MY_OBJECT_ERROR_FOO,
|
||||
MY_OBJECT_ERROR_BAR
|
||||
} MyObjectError;
|
||||
|
||||
#define MY_OBJECT_ERROR my_object_error_quark ()
|
||||
|
||||
gboolean my_object_do_nothing (MyObject *obj, GError **error);
|
||||
|
||||
gboolean my_object_increment (MyObject *obj, gint32 x, int *ret, GError **error);
|
||||
|
||||
gboolean my_object_throw_error (MyObject *obj, GError **error);
|
||||
|
||||
gboolean my_object_uppercase (MyObject *obj, const char *str, char **ret, GError **error);
|
||||
|
||||
gboolean my_object_many_args (MyObject *obj, guint32 x, const char *str, double trouble, double *d_ret, char **str_ret, GError **error);
|
||||
|
||||
#include "test-service-glib-glue.h"
|
||||
|
||||
GQuark my_object_error_quark (void);
|
||||
|
||||
/* Properties */
|
||||
enum
|
||||
{
|
||||
|
|
@ -115,6 +139,54 @@ my_object_class_init (MyObjectClass *mobject_class)
|
|||
"default value",
|
||||
G_PARAM_READWRITE));
|
||||
}
|
||||
|
||||
GQuark
|
||||
my_object_error_quark (void)
|
||||
{
|
||||
static GQuark quark = 0;
|
||||
if (!quark)
|
||||
quark = g_quark_from_static_string ("my_object_error");
|
||||
|
||||
return quark;
|
||||
}
|
||||
|
||||
gboolean
|
||||
my_object_do_nothing (MyObject *obj, GError **error)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
my_object_increment (MyObject *obj, gint32 x, int *ret, GError **error)
|
||||
{
|
||||
*ret = x +1;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
my_object_throw_error (MyObject *obj, GError **error)
|
||||
{
|
||||
g_set_error (error,
|
||||
MY_OBJECT_ERROR,
|
||||
MY_OBJECT_ERROR_FOO,
|
||||
"this method always loses");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
my_object_uppercase (MyObject *obj, const char *str, char **ret, GError **error)
|
||||
{
|
||||
*ret = g_ascii_strup (str, -1);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
my_object_many_args (MyObject *obj, guint32 x, const char *str, double trouble, double *d_ret, char **str_ret, GError **error)
|
||||
{
|
||||
*d_ret = trouble + (x * 2);
|
||||
*str_ret = g_ascii_strup (str, -1);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GMainLoop *loop;
|
||||
|
||||
|
|
@ -148,8 +220,10 @@ main (int argc, char **argv)
|
|||
|
||||
obj = g_object_new (MY_TYPE_OBJECT, NULL);
|
||||
|
||||
dbus_g_object_class_install_info (G_OBJECT_GET_CLASS (obj),
|
||||
&dbus_glib_my_object_object_info);
|
||||
dbus_g_connection_register_g_object (connection,
|
||||
"/org/freedesktop/my_test_object",
|
||||
"/org/freedesktop/DBus/Tests/MyTestObject",
|
||||
obj);
|
||||
|
||||
driver_proxy = dbus_g_proxy_new_for_name (connection,
|
||||
|
|
|
|||
33
test/glib/test-service-glib.xml
Normal file
33
test/glib/test-service-glib.xml
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<node name="/org/freedesktop/DBus/Tests/MyTestObject">
|
||||
|
||||
<interface name="org.freedesktop.DBus.Tests.MyObject" c_name="my_object">
|
||||
|
||||
<method name="DoNothing" c_name="my_object_do_nothing">
|
||||
</method>
|
||||
|
||||
<method name="Increment" c_name="my_object_increment">
|
||||
<arg type="uint32" name="x" />
|
||||
<arg type="uint32" direction="out" />
|
||||
</method>
|
||||
|
||||
<method name="ThrowError" c_name="my_object_throw_error">
|
||||
</method>
|
||||
|
||||
<method name="Uppercase" c_name="my_object_uppercase">
|
||||
<arg type="string" direction="in" />
|
||||
<arg type="string" direction="out" />
|
||||
</method>
|
||||
|
||||
<method name="ManyArgs" c_name="my_object_many_args">
|
||||
<arg type="uint32" name="x" direction="in" />
|
||||
<arg type="string" name="str" direction="in" />
|
||||
<arg type="double" name="trouble" direction="in" />
|
||||
<arg type="double" name="d_ret" direction="out" />
|
||||
<arg type="string" name="str_ret" direction="out" />
|
||||
</method>
|
||||
|
||||
</interface>
|
||||
|
||||
</node>
|
||||
Loading…
Add table
Reference in a new issue