[Pkg-telepathy-commits] [telepathy-glib-1] 24/212: glib-ginterface-gen: register a TpSvcInterfaceInfo, not dbus-glib glue
Simon McVittie
smcv at debian.org
Wed May 14 12:08:47 UTC 2014
This is an automated email from the git hooks/post-receive script.
smcv pushed a commit to branch debian
in repository telepathy-glib-1.
commit b682f339e636d6d367db0557a5f1908c1aa3dea5
Author: Simon McVittie <simon.mcvittie at collabora.co.uk>
Date: Tue Mar 11 18:27:05 2014 +0000
glib-ginterface-gen: register a TpSvcInterfaceInfo, not dbus-glib glue
This allows these interfaces to be exported via GDBus.
---
tools/glib-ginterface-gen.py | 335 ++++++++++++++++++++++---------------------
1 file changed, 173 insertions(+), 162 deletions(-)
diff --git a/tools/glib-ginterface-gen.py b/tools/glib-ginterface-gen.py
index 8cdb18f..d5a786f 100644
--- a/tools/glib-ginterface-gen.py
+++ b/tools/glib-ginterface-gen.py
@@ -27,8 +27,9 @@ import os.path
import xml.dom.minidom
from libtpcodegen import file_set_contents, key_by_name, u, get_emits_changed
-from libglibcodegen import Signature, type_to_gtype, \
- NS_TP, dbus_gutils_wincaps_to_uscore
+from libglibcodegen import (Signature, type_to_gtype,
+ NS_TP, dbus_gutils_wincaps_to_uscore, value_getter,
+ GDBusInterfaceInfo)
NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
@@ -105,15 +106,9 @@ class Generator(object):
iface_emits_changed = get_emits_changed(interface)
- self.b('static const DBusGObjectInfo _%s%s_object_info;'
- % (self.prefix_, node_name_lc))
- self.b('')
-
methods = interface.getElementsByTagName('method')
signals = interface.getElementsByTagName('signal')
properties = interface.getElementsByTagName('property')
- # Don't put properties in dbus-glib glue
- glue_properties = []
self.b('struct _%s%sClass {' % (self.Prefix, node_name_mixed))
self.b(' GTypeInterface parent_class;')
@@ -236,16 +231,75 @@ class Generator(object):
' (G_TYPE_INSTANCE_GET_INTERFACE((obj), %s, %sClass))'
% (self.PREFIX_, node_name_uc, gtype, classname))
self.h('')
- self.h('')
base_init_code = []
+ method_call_code = []
for method in methods:
- self.do_method(method)
+ self.do_method(method, method_call_code)
+
+ signal_table = [
+ 'static const gchar * const _gsignals_%s[] = {' %
+ self.node_name_lc
+ ]
for signal in signals:
- base_init_code.extend(self.do_signal(signal))
+ # we rely on this being in the same order as the interface info
+ self.do_signal(signal, in_base_init=base_init_code,
+ in_signal_table=signal_table)
+
+ signal_table.append(' NULL')
+ signal_table.append('};')
+ signal_table.append('')
+ for line in signal_table:
+ self.b(line)
+
+ # e.g. _interface_info_connection_interface_contact_info1
+ for line in GDBusInterfaceInfo(node_name, interface,
+ '_interface_info_%s' % node_name_lc).to_lines(linkage='static'):
+ self.b(line)
+
+ self.b('')
+ self.b('static void')
+ self.b('_method_call_%s (GDBusConnection *connection,' % node_name_lc)
+ self.b(' const gchar *sender,')
+ self.b(' const gchar *object_path,')
+ self.b(' const gchar *interface_name,')
+ self.b(' const gchar *method_name,')
+ self.b(' GVariant *parameters,')
+ self.b(' GDBusMethodInvocation *invocation,')
+ self.b(' gpointer user_data)')
+ self.b('{')
+ for line in method_call_code:
+ self.b(line)
+
+ # Deliberately not using self.not_implemented_func here so that callers
+ # can distinguish between "you called Protocol.NormalizeContact() but
+ # that isn't implemented here" and "you called Protocol.Badger()
+ # which isn't even in the spec" if required.
+ self.b(' g_dbus_method_invocation_return_error (invocation,')
+ self.b(' G_DBUS_ERROR,')
+ self.b(' G_DBUS_ERROR_UNKNOWN_METHOD,')
+ self.b(' "Method not implemented");')
+ self.b('}')
+ self.b('')
+ self.b('static const GDBusInterfaceVTable _vtable_%s = {' %
+ node_name_lc)
+ self.b(' _method_call_%s,' % node_name_lc)
+ self.b(' NULL, /* get property */')
+ self.b(' NULL /* set property */')
+ self.b('};')
+ self.b('')
+ self.b('static const TpSvcInterfaceInfo _tp_interface_info_%s = {' %
+ node_name_lc)
+ self.b(' -1,')
+ self.b(' (GDBusInterfaceInfo *) &_interface_info_%s,' % node_name_lc)
+ self.b(' (GDBusInterfaceVTable *) &_vtable_%s,' % node_name_lc)
+ self.b(' (gchar **) _gsignals_%s' % node_name_lc)
+ self.b(' /* _future is implicitly zero-filled */')
+ self.b('};')
+ self.b('')
self.b('static inline void')
self.b('%s%s_base_init_once (gpointer klass G_GNUC_UNUSED)'
% (self.prefix_, node_name_lc))
@@ -286,13 +340,6 @@ class Generator(object):
self.b(' { 0, properties, NULL, NULL };')
self.b('')
-
- self.b(' dbus_g_object_type_install_info (%s%s_get_type (),'
- % (self.prefix_, node_name_lc))
- self.b(' &_%s%s_object_info);'
- % (self.prefix_, node_name_lc))
- self.b('')
-
if properties:
self.b(' interface.dbus_interface = g_quark_from_static_string '
'("%s");' % self.iface_name)
@@ -308,6 +355,10 @@ class Generator(object):
self.b('')
+ self.b(' tp_svc_interface_set_dbus_interface_info (%s,'
+ % (self.current_gtype))
+ self.b(' &_tp_interface_info_%s);' % node_name_lc)
+
for s in base_init_code:
self.b(s)
self.b('}')
@@ -329,100 +380,10 @@ class Generator(object):
self.h('')
- self.b('static const DBusGMethodInfo _%s%s_methods[] = {'
- % (self.prefix_, node_name_lc))
-
- method_blob, offsets = self.get_method_glue(methods)
-
- for method, offset in zip(methods, offsets):
- self.do_method_glue(method, offset)
-
- if len(methods) == 0:
- # empty arrays are a gcc extension, so put in a dummy member
- self.b(" { NULL, NULL, 0 }")
-
- self.b('};')
- self.b('')
-
- self.b('static const DBusGObjectInfo _%s%s_object_info = {'
- % (self.prefix_, node_name_lc))
- self.b(' 0,') # version
- self.b(' _%s%s_methods,' % (self.prefix_, node_name_lc))
- self.b(' %d,' % len(methods))
- self.b('"' + method_blob.replace('\0', '\\0') + '",')
- self.b('"' + self.get_signal_glue(signals).replace('\0', '\\0') + '",')
- self.b('"' +
- self.get_property_glue(glue_properties).replace('\0', '\\0') +
- '",')
- self.b('};')
- self.b('')
-
self.node_name_mixed = None
self.node_name_lc = None
self.node_name_uc = None
- def get_method_glue(self, methods):
- info = []
- offsets = []
-
- for method in methods:
- offsets.append(len(''.join(info)))
-
- info.append(self.iface_name + '\0')
- info.append(method.getAttribute('name') + '\0')
-
- info.append('A\0') # async
-
- counter = 0
- for arg in method.getElementsByTagName('arg'):
- out = arg.getAttribute('direction') == 'out'
-
- name = arg.getAttribute('name')
- if not name:
- assert out
- name = 'arg%u' % counter
- counter += 1
-
- info.append(name + '\0')
-
- if out:
- info.append('O\0')
- else:
- info.append('I\0')
-
- if out:
- info.append('F\0') # not const
- info.append('N\0') # not error or return
- info.append(arg.getAttribute('type') + '\0')
-
- info.append('\0')
-
- return ''.join(info) + '\0', offsets
-
- def do_method_glue(self, method, offset):
- lc_name = method.getAttribute('tp:name-for-bindings')
- if method.getAttribute('name') != lc_name.replace('_', ''):
- raise AssertionError('Method %s tp:name-for-bindings (%s) does '
- 'not match' % (method.getAttribute('name'), lc_name))
- lc_name = lc_name.lower()
-
- marshaller = 'g_cclosure_marshal_generic'
- wrapper = self.prefix_ + self.node_name_lc + '_' + lc_name
-
- self.b(" { (GCallback) %s, %s, %d }," % (wrapper, marshaller, offset))
-
- def get_signal_glue(self, signals):
- info = []
-
- for signal in signals:
- info.append(self.iface_name)
- info.append(signal.getAttribute('name'))
-
- return '\0'.join(info) + '\0\0'
-
- # the implementation can be the same
- get_property_glue = get_signal_glue
-
def get_method_impl_names(self, method):
dbus_method_name = method.getAttribute('name')
@@ -436,11 +397,9 @@ class Generator(object):
class_member_name)
return (stub_name + '_impl', class_member_name + '_cb')
- def do_method(self, method):
+ def do_method(self, method, method_call_code):
assert self.node_name_mixed is not None
- in_class = []
-
# Examples refer to Thing.DoStuff (su) -> ii
# DoStuff
@@ -452,20 +411,20 @@ class Generator(object):
'not match' % (dbus_method_name, class_member_name))
class_member_name = class_member_name.lower()
- # void tp_svc_thing_do_stuff (TpSvcThing *, const char *, guint,
- # DBusGMethodInvocation *);
+ # tp_svc_thing_do_stuff (signature of GDBusInterfaceMethodCallFunc)
stub_name = (self.prefix_ + self.node_name_lc + '_' +
class_member_name)
# typedef void (*tp_svc_thing_do_stuff_impl) (TpSvcThing *,
- # const char *, guint, DBusGMethodInvocation);
+ # const char *, guint, GDBusMethodInvocation);
impl_name = stub_name + '_impl'
- # void tp_svc_thing_return_from_do_stuff (DBusGMethodInvocation *,
+ # void tp_svc_thing_return_from_do_stuff (GDBusMethodInvocation *,
# gint, gint);
ret_name = (self.prefix_ + self.node_name_lc + '_return_from_' +
class_member_name)
# Gather arguments
in_args = []
+ in_arg_value_getters = []
out_args = []
for i in method.getElementsByTagName('arg'):
name = i.getAttribute('name')
@@ -489,9 +448,22 @@ class Generator(object):
struct = (ctype, name)
if direction == 'in':
- in_args.append(struct)
+ in_args.append((ctype, name))
+ in_arg_value_getters.append(value_getter(gtype, marshaller))
else:
- out_args.append(struct)
+ out_args.append((gtype, ctype, name))
+
+ # bits of _method_call_myiface
+ method_call_code.extend([
+ ' if (g_strcmp0 (method_name, "%s") == 0)' % dbus_method_name,
+ ' {',
+ ' %s (connection, sender, object_path, interface_name, ' %
+ stub_name,
+ ' method_name, parameters, invocation, user_data);',
+ ' return;',
+ ' }',
+ ''
+ ])
# Implementation type declaration (in header, docs separated)
self.d('/**')
@@ -500,7 +472,7 @@ class Generator(object):
for (ctype, name) in in_args:
self.d(' * @%s: %s (FIXME, generate documentation)'
% (name, ctype))
- self.d(' * @context: Used to return values or throw an error')
+ self.d(' * @invocation: Used to return values or throw an error')
self.d(' *')
self.d(' * The signature of an implementation of the D-Bus method')
self.d(' * %s on interface %s.' % (dbus_method_name, self.iface_name))
@@ -510,37 +482,59 @@ class Generator(object):
% (impl_name, self.Prefix, self.node_name_mixed))
for (ctype, name) in in_args:
self.h(' %s%s,' % (ctype, name))
- self.h(' DBusGMethodInvocation *context);')
-
- # Class member (in class definition)
- in_class.append(' %s %s;' % (impl_name, class_member_name))
+ self.h(' GDBusMethodInvocation *invocation);')
# Stub definition (in body only - it's static)
self.b('static void')
- self.b('%s (%s%s *self,'
- % (stub_name, self.Prefix, self.node_name_mixed))
- for (ctype, name) in in_args:
- self.b(' %s%s,' % (ctype, name))
- self.b(' DBusGMethodInvocation *context)')
+ self.b('%s (GDBusConnection *connection,' % stub_name)
+ self.b(' const gchar *sender,')
+ self.b(' const gchar *object_path,')
+ self.b(' const gchar *interface_name,')
+ self.b(' const gchar *method_name,')
+ self.b(' GVariant *parameters,')
+ self.b(' GDBusMethodInvocation *invocation,')
+ self.b(' gpointer user_data)')
self.b('{')
- self.b(' %s impl = (%s%s_GET_CLASS (self)->%s_cb);'
- % (impl_name, self.PREFIX_, self.node_name_uc, class_member_name))
+ self.b(' %s%s *self = %s%s (user_data);'
+ % (self.Prefix, self.node_name_mixed, self.PREFIX_,
+ self.node_name_uc))
+ self.b(' %s%sClass *cls = %s%s_GET_CLASS (self);'
+ % (self.Prefix, self.node_name_mixed, self.PREFIX_,
+ self.node_name_uc))
+ self.b(' %s impl = cls->%s_cb;' % (impl_name, class_member_name))
self.b('')
self.b(' if (impl != NULL)')
- tmp = ['self'] + [name for (ctype, name) in in_args] + ['context']
+ tmp = ['self'] + [name for (ctype, name) in in_args] + ['invocation']
self.b(' {')
- self.b(' (impl) (%s);' % ',\n '.join(tmp))
+
+ if in_args:
+ self.b(' GValue args_val = G_VALUE_INIT;')
+ self.b(' GValueArray *va;')
+ self.b('')
+ self.b(' dbus_g_value_parse_g_variant (parameters, &args_val);')
+ self.b(' va = g_value_get_boxed (&args_val);')
+ self.b('')
+
+ self.b(' (impl) (self,')
+
+ for i, getter in enumerate(in_arg_value_getters):
+ self.b(' %s (va->values + %d),' % (getter, i))
+
+ self.b(' invocation);')
+
+ if in_args:
+ self.b(' g_value_unset (&args_val);')
+
self.b(' }')
self.b(' else')
self.b(' {')
if self.not_implemented_func:
- self.b(' %s (context);' % self.not_implemented_func)
+ self.b(' %s (invocation);' % self.not_implemented_func)
else:
- self.b(' GError e = { DBUS_GERROR, ')
- self.b(' DBUS_GERROR_UNKNOWN_METHOD,')
- self.b(' "Method not implemented" };')
- self.b('')
- self.b(' dbus_g_method_return_error (context, &e);')
+ self.b(' g_dbus_method_invocation_return_error (invocation,')
+ self.b(' G_DBUS_ERROR,')
+ self.b(' G_DBUS_ERROR_UNKNOWN_METHOD,')
+ self.b(' "Method not implemented");')
self.b(' }')
self.b('}')
self.b('')
@@ -572,44 +566,59 @@ class Generator(object):
self.b('}')
self.b('')
- # Return convenience function (static inline, in header)
+ # Return convenience function
self.d('/**')
self.d(' * %s:' % ret_name)
- self.d(' * @context: The D-Bus method invocation context')
- for (ctype, name) in out_args:
+ self.d(' * @invocation: The D-Bus method invocation context')
+ for (gtype, ctype, name) in out_args:
self.d(' * @%s: %s (FIXME, generate documentation)'
% (name, ctype))
self.d(' *')
- self.d(' * Return successfully by calling dbus_g_method_return().')
- self.d(' * This inline function exists only to provide type-safety.')
+ self.d(' * Return successfully by calling g_dbus_method_invocation_return_value().')
self.d(' */')
self.d('')
- tmp = (['DBusGMethodInvocation *context'] +
- [ctype + name for (ctype, name) in out_args])
- self.h('static inline')
- self.h('/* this comment is to stop gtkdoc realising this is static */')
+ tmp = (['GDBusMethodInvocation *invocation'] +
+ [ctype + name for (gtype, ctype, name) in out_args])
self.h(('void %s (' % ret_name) + (',\n '.join(tmp)) + ');')
- self.h('static inline void')
- self.h(('%s (' % ret_name) + (',\n '.join(tmp)) + ')')
- self.h('{')
- tmp = ['context'] + [name for (ctype, name) in out_args]
- self.h(' dbus_g_method_return (' + ',\n '.join(tmp) + ');')
- self.h('}')
- self.h('')
- return in_class
+ self.b('void')
+ self.b(('%s (' % ret_name) + (',\n '.join(tmp)) + ')')
+ self.b('{')
+ self.b(' GValueArray *tmp = tp_value_array_build (%d,' % len(out_args))
+
+ for (gtype, ctype, name) in out_args:
+ self.b(' %s, %s,' % (gtype, name))
+
+ self.b(' G_TYPE_INVALID);')
+ self.b(' GValue args_val = G_VALUE_INIT;')
+ self.b('')
+
+ self.b(' g_value_init (&args_val, '
+ 'dbus_g_type_get_struct ("GValueArray",')
+
+ for (gtype, ctype, name) in out_args:
+ self.b(' %s,' % gtype)
+
+ self.b(' G_TYPE_INVALID));')
+
+ self.b(' g_value_take_boxed (&args_val, tmp);')
+
+ self.b(' g_dbus_method_invocation_return_value (invocation,')
+ self.b(' /* consume floating ref */')
+ self.b(' dbus_g_value_build_g_variant (&args_val));')
+ self.b(' g_value_unset (&args_val);')
+ self.b('}')
+ self.b('')
def get_signal_const_entry(self, signal):
assert self.node_name_uc is not None
return ('SIGNAL_%s_%s'
% (self.node_name_uc, signal.getAttribute('name')))
- def do_signal(self, signal):
+ def do_signal(self, signal, in_base_init, in_signal_table):
assert self.node_name_mixed is not None
- in_base_init = []
-
# for signal: Thing::StuffHappened (s, u)
# we want to emit:
# void tp_svc_thing_emit_stuff_happened (gpointer instance,
@@ -707,7 +716,7 @@ class Generator(object):
in_base_init.append(' %s);' % ',\n '.join(tmp))
in_base_init.append('')
- return in_base_init
+ in_signal_table.append(' "%s",' % signal_name)
def have_properties(self, nodes):
for node in nodes:
@@ -721,6 +730,7 @@ class Generator(object):
nodes.sort(key=key_by_name)
self.h('#include <glib-object.h>')
+ self.h('#include <gio/gio.h>')
self.h('#include <dbus/dbus-glib.h>')
self.h('')
@@ -731,9 +741,10 @@ class Generator(object):
self.b('')
if self.allow_single_include:
+ self.b('#include <telepathy-glib/core-svc-interface.h>')
self.b('#include <telepathy-glib/dbus.h>')
- if self.have_properties(nodes):
- self.b('#include <telepathy-glib/dbus-properties-mixin.h>')
+ self.b('#include <telepathy-glib/dbus-properties-mixin.h>')
+ self.b('#include <telepathy-glib/util.h>')
else:
self.b('#include <telepathy-glib/telepathy-glib.h>')
self.b('')
@@ -776,9 +787,9 @@ options:
--not-implemented-func='symbol'
Set action when methods not implemented in the interface vtable are
called. symbol must have signature
- void symbol (DBusGMethodInvocation *context)
+ void symbol (GDBusMethodInvocation *invocation)
and return some sort of "not implemented" error via
- dbus_g_method_return_error (context, ...)
+ e.g. g_dbus_method_invocation_return_error
""")
sys.exit(1)
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-telepathy/telepathy-glib-1.git
More information about the Pkg-telepathy-commits
mailing list