[glibmm] Gio::DBus: Minor API changes.



commit 55efa327a0c7a29ed2b4050dc9b081146d87ace3
Author: Murray Cumming <murrayc murrayc com>
Date:   Fri Apr 1 11:56:20 2011 +0200

    Gio::DBus: Minor API changes.
    
      * gio/src/dbusconnection.[hg|ccg]: register_object(), register_subtree():
      Take the VTable by reference, not pointer. register_object() can take a NULL
      but that needs documentation (see the bug mentioned) and a future method
      overload.
      * gio/src/dbusmethodinvocation.ccg: get_parameters(): Return a
      VariantContainerBase instead of taking a VariantBase output parameter,
      because this is always a tuple. Well, I think so: See the bug mentioned.
      * gio/src/dbusmethodinvocation.hg: return_value(): Take a VariantContainerBase
      instead of a VariantBase, because this is always a tuple.
      return_gerror(), return_error_literal(): Rename them both to return_error().
      * glib/src/variant.hg: VariantContainerBase::create_tuple(): Add a method
      overload that takes a single VariantBase, for convenience, so that applications
      don't need to create a single-item vector.
    * examples/dbus/busserver.cc: Adapted.
    * examples/dbus/busserver.cc: Rename to server.cc and actually implement it,
    though I am currently confused about whether this server's object should be
    available on an existing bus. Maybe we should use Gio::DBus::own_name()
    instead of Gio::DBus::Server.

 ChangeLog                                 |   23 +++++
 examples/Makefile.am                      |    6 +-
 examples/dbus/peer.cc                     |   31 ++----
 examples/dbus/{busserver.cc => server.cc} |  153 ++++++++++++++++++-----------
 gio/src/dbusconnection.ccg                |   10 +-
 gio/src/dbusconnection.hg                 |    8 +-
 gio/src/dbusmethodinvocation.ccg          |   10 --
 gio/src/dbusmethodinvocation.hg           |   20 ++--
 glib/src/variant.ccg                      |    9 ++
 glib/src/variant.hg                       |    6 +
 tools/m4/convert_gio.m4                   |    1 +
 11 files changed, 165 insertions(+), 112 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 0394d59..68317c3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,28 @@
 2011-04-01  Murray Cumming  <murrayc murrayc com>
 
+	Gio::DBus: Minor API changes.
+
+  * gio/src/dbusconnection.[hg|ccg]: register_object(), register_subtree():
+  Take the VTable by reference, not pointer. register_object() can take a NULL
+  but that needs documentation (see the bug mentioned) and a future method
+  overload.
+  * gio/src/dbusmethodinvocation.ccg: get_parameters(): Return a
+  VariantContainerBase instead of taking a VariantBase output parameter,
+  because this is always a tuple. Well, I think so: See the bug mentioned.
+  * gio/src/dbusmethodinvocation.hg: return_value(): Take a VariantContainerBase
+  instead of a VariantBase, because this is always a tuple.
+  return_gerror(), return_error_literal(): Rename them both to return_error().
+  * glib/src/variant.hg: VariantContainerBase::create_tuple(): Add a method
+  overload that takes a single VariantBase, for convenience, so that applications
+  don't need to create a single-item vector.
+	* examples/dbus/busserver.cc: Adapted.
+	* examples/dbus/busserver.cc: Rename to server.cc and actually implement it,
+	though I am currently confused about whether this server's object should be
+	available on an existing bus. Maybe we should use Gio::DBus::own_name()
+	instead of Gio::DBus::Server.
+
+2011-04-01  Murray Cumming  <murrayc murrayc com>
+
 	Rename a D-Bus client example.
 
 	* examples/dbus/userbus.cc: Rename to client_bus_listnames.cc to make it
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 0cbf20e..fa772e3 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -20,7 +20,7 @@ AUTOMAKE_OPTIONS = subdir-objects
 check_PROGRAMS =			\
 	child_watch/child_watch		\
 	compose/example			\
-	dbus/busserver			\
+	dbus/server			\
 	dbus/peer			\
 	dbus/client_bus_listnames \
 	iochannel_stream/example	\
@@ -76,8 +76,8 @@ thread_threadpool_SOURCES  = thread/threadpool.cc
 thread_threadpool_LDADD    = $(thread_ldadd)
 
 # giomm examples
-dbus_busserver_SOURCES = dbus/busserver.cc
-dbus_busserver_LDADD   = $(giomm_ldadd)
+dbus_server_SOURCES = dbus/server.cc
+dbus_server_LDADD   = $(giomm_ldadd)
 dbus_peer_SOURCES = dbus/peer.cc
 dbus_peer_LDADD = $(giomm_ldadd)
 dbus_client_bus_listnames_SOURCES = dbus/client_bus_listnames.cc
diff --git a/examples/dbus/peer.cc b/examples/dbus/peer.cc
index 55b8128..5d80d70 100644
--- a/examples/dbus/peer.cc
+++ b/examples/dbus/peer.cc
@@ -108,30 +108,22 @@ static Glib::RefPtr<Gio::DBus::Connection> curr_connection;
 static void on_method_call(const Glib::RefPtr<Gio::DBus::Connection>&,
   const Glib::ustring& /* sender */, const Glib::ustring& /* object_path */,
   const Glib::ustring& /* interface_name */, const Glib::ustring& method_name,
-  // Since the parameters are generally tuples, get them from the invocation.
-  const Glib::VariantBase& /* parameters */,
+  const Glib::VariantContainerBase& parameters,
   const Glib::RefPtr<Gio::DBus::MethodInvocation>& invocation)
 {
   if(method_name == "HelloWorld")
   {
-    // Get parameters.
-    Glib::VariantContainerBase parameters;
-    invocation->get_parameters(parameters);
-
     // Get (expected) single string in tupple.
     Glib::Variant<Glib::ustring> param;
     parameters.get_child(param);
 
-    Glib::ustring response = "You said: '" + param.get() + "'.";
+    const Glib::ustring response = "You said: '" + param.get() + "'.";
 
-    Glib::Variant<Glib::ustring> answer =
+    const Glib::Variant<Glib::ustring> answer =
       Glib::Variant<Glib::ustring>::create(response);
 
-    std::vector<Glib::VariantBase> var_array;
-    var_array.push_back(answer);
-
-    Glib::VariantContainerBase ret =
-      Glib::VariantContainerBase::create_tuple(var_array);
+    const Glib::VariantContainerBase ret =
+      Glib::VariantContainerBase::create_tuple(answer);
 
     invocation->return_value(ret);
 
@@ -175,9 +167,9 @@ bool on_new_connection(const Glib::RefPtr<Gio::DBus::Connection>& connection)
   // connection must be kept so store the connection in a global variable.
   curr_connection = connection;
 
-  guint reg_id = connection->register_object("/org/glibmm/DBus/TestObject",
+  const guint reg_id = connection->register_object("/org/glibmm/DBus/TestObject",
     introspection_data->lookup_interface("org.glibmm.DBus.TestPeerInterface"),
-    &interface_vtable);
+    interface_vtable);
 
   if(reg_id == 0)
   {
@@ -249,14 +241,11 @@ void run_as_client(const Glib::ustring& address)
 
   Glib::ustring greeting("Hello, it's: "  + time.as_iso8601() + '.');
 
-  Glib::Variant<Glib::ustring> param =
+  const Glib::Variant<Glib::ustring> param =
     Glib::Variant<Glib::ustring>::create(greeting);
 
-  std::vector<Glib::VariantBase> variants;
-  variants.push_back(param);
-
-  Glib::VariantContainerBase parameters =
-    Glib::VariantContainerBase::create_tuple(variants);
+  const Glib::VariantContainerBase parameters =
+    Glib::VariantContainerBase::create_tuple(param);
 
   try
   {
diff --git a/examples/dbus/busserver.cc b/examples/dbus/server.cc
similarity index 55%
rename from examples/dbus/busserver.cc
rename to examples/dbus/server.cc
index 3beeca2..6ebe0ea 100644
--- a/examples/dbus/busserver.cc
+++ b/examples/dbus/server.cc
@@ -38,29 +38,26 @@ static Glib::RefPtr<Gio::DBus::NodeInfo> introspection_data;
 static Glib::ustring introspection_xml =
   "<node>"
   "  <interface name='org.glibmm.DBus.Clock'>"
-  "    <method name='GetTime'>"
+  "    <method name='GetTime' />"
   "    <method name='SetAlarm'>"
   "      <arg type='s' name='iso8601' direction='in'/>"
   "    </method>"
-  "    <method name='GetStdout'>"
-  "    <signal name='OnAlarm'>"
-  "      <arg type='s' name='iso8601'/>"
-  "    </signal>"
-       // The time of the alarm as an iso8601 string.
-  "    <property type='s' name='Alarm' access='readwrite'/>"
   "  </interface>"
   "</node>";
 
 // Stores the current alarm.
 static Glib::TimeVal curr_alarm;
 
+// This variable is used to keep an incoming connection active until it is
+// closed.
+static Glib::RefPtr<Gio::DBus::Connection> current_connection;
+
 } // anonymous namespace
 
-/* TODO: This code does not seem to be used. murrayc.
 static void on_method_call(const Glib::RefPtr<Gio::DBus::Connection>& connection,
-  const Glib::ustring& sender, const Glib::ustring& object_path,
-  const Glib::ustring& interface_name, const Glib::ustring& method_name,
-  const Glib::VariantBase& parameters,
+  const Glib::ustring& /* sender */, const Glib::ustring& /* object_path */,
+  const Glib::ustring& /* interface_name */, const Glib::ustring& method_name,
+  const Glib::VariantContainerBase& parameters,
   const Glib::RefPtr<Gio::DBus::MethodInvocation>& invocation)
 {
   if(method_name == "GetTime")
@@ -68,18 +65,13 @@ static void on_method_call(const Glib::RefPtr<Gio::DBus::Connection>& connection
     Glib::TimeVal curr_time;
     curr_time.assign_current_time();
 
-    Glib::ustring time_str = curr_time.as_iso8601();
-
-    Glib::Variant<Glib::ustring> time_var =
+    const Glib::ustring time_str = curr_time.as_iso8601();
+    const Glib::Variant<Glib::ustring> time_var =
       Glib::Variant<Glib::ustring>::create(time_str);
 
-    // Create a variant array to create a tuple to be returned to the client.
-    std::vector<Glib::VariantBase> var_array;
-    var_array.push_back(time_var);
-
     // Create the tuple.
     Glib::VariantContainerBase response =
-      Glib::VariantContainerBase::create_tuple(var_array);
+      Glib::VariantContainerBase::create_tuple(time_var);
 
     // Return the tuple with the included time.
     invocation->return_value(response);
@@ -87,29 +79,29 @@ static void on_method_call(const Glib::RefPtr<Gio::DBus::Connection>& connection
   else if(method_name == "SetAlarm")
   {
     // Get the parameter tuple.
-    Glib::VariantContainerBase parameters;
-    invocation->get_parameters(parameters);
+    //Glib::VariantContainerBase parameters;
+    //invocation->get_parameters(parameters);
 
     // Get the variant string.
     Glib::Variant<Glib::ustring> param;
-    parameters.get(param);
+    parameters.get_child(param);
 
     // Get the time string.
-    Glib::ustring time_str = param.get();
+    const Glib::ustring time_str = param.get();
 
     if(!curr_alarm.assign_from_iso8601(time_str))
     {
       // If setting alarm was not successful, return an error.
       Gio::DBus::Error error(Gio::DBus::Error::INVALID_ARGS,
           "Alarm string is not in ISO8601 format.");
-      invocation->return_gerror(error);
+      invocation->return_error(error);
     }
   }
   else if(method_name == "GetStdout")
   {
 #ifndef G_OS_WIN32
     if(connection->get_capabilities() &
-      Gio::DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING)
+      Gio::DBus::CAPABILITY_FLAGS_UNIX_FD_PASSING)
     {
       Glib::RefPtr<Gio::UnixFDList> list = Gio::UnixFDList::create();
       try
@@ -146,57 +138,100 @@ static void on_method_call(const Glib::RefPtr<Gio::DBus::Connection>& connection
     // Non-existent method on the interface.
     Gio::DBus::Error error(Gio::DBus::Error::UNKNOWN_METHOD,
       "Method does not exist.");
-    invocation->return_gerror(error);
+    invocation->return_error(error);
   }
 }
-*/
 
-void on_get_property(Glib::VariantBase& property,
-  const Glib::RefPtr<Gio::DBus::Connection>& /* connection */,
-  const Glib::ustring& /* sender */, const Glib::ustring& /* object_path */,
-  const Glib::ustring& /* interface_name */, const Glib::ustring& property_name)
+bool on_server_new_connection(const Glib::RefPtr<Gio::DBus::Connection>& connection)
 {
-  if(property_name == "Alarm")
-  {
-    if(curr_alarm.valid())
-    {
-      Glib::ustring alarm_str = curr_alarm.as_iso8601();
+  Glib::RefPtr<Gio::Credentials> credentials =
+    connection->get_peer_credentials();
 
-      Glib::Variant<Glib::ustring> alarm_var =
-        Glib::Variant<Glib::ustring>::create(alarm_str);
+  std::string credentials_str;
 
-      property = alarm_var;
-    }
-    else
-    {
-      throw Gio::Error(Gio::Error::FAILED, "Alarm has not been set.");
-    }
-  }
+  if(!credentials)
+    credentials_str = "(no credentials received)";
   else
-  {
-    throw Gio::DBus::Error(Gio::DBus::Error::FAILED, "Unknown property name.");
-  }
-}
+    credentials_str = credentials->to_string();
 
-/** TODO: This code does not seem to be used. murrayc.
-bool on_set_property(const Glib::RefPtr<Gio::DBus::Connection>& connection,
-  const Glib::ustring& sender, const Glib::ustring& object_path,
-  const Glib::ustring& interface_name, const Glib::ustring& property_name,
-  const Glib::VariantBase& value)
-{
-  if(property_name == "Alarm")
+  std::cout <<
+    "Client connected." << std::endl <<
+    "Peer credentials: " << credentials_str << std::endl <<
+    "Negotiated capabilities: unix-fd-passing=" << (connection->get_capabilities() & Gio::DBus::CAPABILITY_FLAGS_UNIX_FD_PASSING) << std::endl;
+
+  // If there is already an active connection, do not accept this new one.
+  // There may be a better way to decide how to keep current incoming
+  // connections.
+  if(current_connection && !current_connection->is_closed())
   {
+    std::cerr << "Unable to accept a new incoming connection because one is "
+      "already active." << std::endl;
+
+    return false;
   }
-  else
+
+  // In order for the connection to stay active the reference to the
+  // connection must be kept, so store the connection in a global variable:
+  current_connection = connection;
+
+  // See https://bugzilla.gnome.org/show_bug.cgi?id=646417 about avoiding
+  // the repetition of the interface name:
+  const Gio::DBus::InterfaceVTable interface_vtable(sigc::ptr_fun(&on_method_call));
+  const guint reg_id = connection->register_object("/org/glibmm/DBus/TestObject",
+    introspection_data->lookup_interface("org.glibmm.DBus.Clock"),
+    interface_vtable);
+
+  if(reg_id == 0)
   {
+    std::cerr << "Registration of object for incoming connection not "
+      "possible." << std::endl;
+    return false;
   }
+
+  return true;
 }
-*/
 
 int main(int, char**)
 {
   std::locale::global(std::locale(""));
   Gio::init();
 
-  return 0;
+ try
+  {
+    introspection_data = Gio::DBus::NodeInfo::create_for_xml(introspection_xml);
+  }
+  catch(const Glib::Error& ex)
+  {
+    std::cerr << "Unable to create introspection data: " << ex.what() <<
+      "." << std::endl;
+    return 1;
+  }
+
+  Glib::RefPtr<Gio::DBus::Server> server;
+
+  const Glib::ustring address = "unix:abstract=myadd";
+  try
+  {
+    server = Gio::DBus::Server::create_sync(address,
+      Gio::DBus::generate_guid());
+  }
+  catch(const Glib::Error& ex)
+  {
+    std::cerr << "Error creating server at address: " << address <<
+      ": " << ex.what() << "." << std::endl;
+    return EXIT_FAILURE;
+  }
+
+  server->start();
+
+  std::cout << "Server is listening at: " << server->get_client_address() <<
+    "." << std::endl;
+
+  server->signal_new_connection().connect(sigc::ptr_fun(&on_server_new_connection));
+
+  //Keep the server running until the process is killed:
+  Glib::RefPtr<Glib::MainLoop> loop = Glib::MainLoop::create();
+  loop->run();
+
+  return EXIT_SUCCESS;
 }
diff --git a/gio/src/dbusconnection.ccg b/gio/src/dbusconnection.ccg
index 273647f..99e9d83 100644
--- a/gio/src/dbusconnection.ccg
+++ b/gio/src/dbusconnection.ccg
@@ -799,13 +799,13 @@ guint Connection::add_filter(const SlotMessageFilter& slot)
 
 guint Connection::register_object(const Glib::ustring& object_path,
   const Glib::RefPtr<InterfaceInfo>& interface_info,
-  const InterfaceVTable* vtable)
+  const InterfaceVTable& vtable)
 {
   GError* gerror = 0;
 
   const guint result = g_dbus_connection_register_object(gobj(),
     object_path.c_str(), Glib::unwrap(interface_info),
-    vtable->gobj(), const_cast<InterfaceVTable*>(vtable), 0, &gerror);
+    vtable.gobj(), const_cast<InterfaceVTable*>(&vtable), 0, &gerror);
 
   if(gerror)
     ::Glib::Error::throw_exception(gerror);
@@ -814,14 +814,14 @@ guint Connection::register_object(const Glib::ustring& object_path,
 }
 
 guint Connection::register_subtree(const Glib::ustring& object_path,
-  const SubtreeVTable* vtable, SubtreeFlags flags)
+  const SubtreeVTable& vtable, SubtreeFlags flags)
 {
   GError* gerror = 0;
 
   const guint result = g_dbus_connection_register_subtree(gobj(),
     object_path.c_str(),
-    vtable->gobj(), static_cast<GDBusSubtreeFlags>(flags),
-    const_cast<SubtreeVTable*>(vtable), 0, &gerror);
+    vtable.gobj(), static_cast<GDBusSubtreeFlags>(flags),
+    const_cast<SubtreeVTable*>(&vtable), 0, &gerror);
 
   if(gerror)
     ::Glib::Error::throw_exception(gerror);
diff --git a/gio/src/dbusconnection.hg b/gio/src/dbusconnection.hg
index 1295ec5..d3069be 100644
--- a/gio/src/dbusconnection.hg
+++ b/gio/src/dbusconnection.hg
@@ -838,6 +838,8 @@ public:
 
   _WRAP_METHOD(void remove_filter(guint filter_id), g_dbus_connection_remove_filter)
 
+  //TODO: See https://bugzilla.gnome.org/show_bug.cgi?id=646419 about
+  //vtable being allowed to be NULL, which would need a method overload.
   /** Registers slots for exported objects at @a object_path with the D-Bus
    * interface that is described in @a interface_info.
    *
@@ -870,7 +872,7 @@ public:
    *
    * @param object_path The object path to register at.
    * @param interface_info Introspection data for the interface.
-   * @param vtable An InterfaceVTable to call into or NULL.
+   * @param vtable An InterfaceVTable to call into.
    * @return A registration id (never 0) that can be used with
    * unregister_object() if no Glib::Error is thrown.
    * @throw Glib::Error.
@@ -878,7 +880,7 @@ public:
    */
   guint register_object(const Glib::ustring& object_path,
     const Glib::RefPtr<InterfaceInfo>& interface_info,
-    const InterfaceVTable* vtable);
+    const InterfaceVTable& vtable);
   _IGNORE(g_dbus_connection_register_object)
 
   _WRAP_METHOD(bool unregister_object(guint registration_id), g_dbus_connection_unregister_object)
@@ -920,7 +922,7 @@ public:
    * @newin{2,28}
    */
   guint register_subtree(const Glib::ustring& object_path,
-    const SubtreeVTable* vtable,
+    const SubtreeVTable& vtable,
     SubtreeFlags flags = Gio::DBus::SUBTREE_FLAGS_NONE);
   _IGNORE(g_dbus_connection_register_subtree)
 
diff --git a/gio/src/dbusmethodinvocation.ccg b/gio/src/dbusmethodinvocation.ccg
index 7d29db4..ca113ed 100644
--- a/gio/src/dbusmethodinvocation.ccg
+++ b/gio/src/dbusmethodinvocation.ccg
@@ -28,16 +28,6 @@ namespace Gio
 namespace DBus
 {
 
-void MethodInvocation::get_parameters(Glib::VariantBase& value) const
-{
-  GVariant* const g_value = g_dbus_method_invocation_get_parameters(const_cast<GDBusMethodInvocation*>(gobj()));
-
-  if(!g_value)
-    return;
-
-  value.init(g_value, true /* take a reference */);
-}
-
 } // namespace DBus
 
 } // namespace Gio
diff --git a/gio/src/dbusmethodinvocation.hg b/gio/src/dbusmethodinvocation.hg
index dde8685..ffb7ee1 100644
--- a/gio/src/dbusmethodinvocation.hg
+++ b/gio/src/dbusmethodinvocation.hg
@@ -68,22 +68,20 @@ public:
   _WRAP_METHOD(Glib::RefPtr<Message> get_message(), g_dbus_method_invocation_get_message, refreturn)
   _WRAP_METHOD(Glib::RefPtr<const Message> get_message() const, g_dbus_method_invocation_get_message, refreturn, constversion)
 
-  /** Gets the parameters of the method invocation.
-   *
-   * @param value The location in which to return the parameters.
-   *
-   * @newin{2,28}
-   */
-  void get_parameters(Glib::VariantBase& value) const;
-  _IGNORE(g_dbus_method_invocation_get_parameters)
+  //We assume that this is a tuple (VariantContainerBase).
+  //See https://bugzilla.gnome.org/show_bug.cgi?id=646420
+  _WRAP_METHOD(Glib::VariantContainerBase get_parameters() const, g_dbus_method_invocation_get_parameters)
 
-  _WRAP_METHOD(void return_value(const Glib::VariantBase& parameters), g_dbus_method_invocation_return_value)
+  //TODO: Add a return_single_value() method?
+  //A return_value(VariantBase) would probably be ambiguous to people
+  //even if it isn't ambiguous to the compiler.
+  _WRAP_METHOD(void return_value(const Glib::VariantContainerBase& parameters), g_dbus_method_invocation_return_value)
 
 #m4 _CONVERSION(`const Glib::ustring&', `GQuark', `Glib::QueryQuark($3).id()')
-  _WRAP_METHOD(void return_error_literal(const Glib::ustring& domain, int code, const Glib::ustring& message), g_dbus_method_invocation_return_error_literal)
+  _WRAP_METHOD(void return_error(const Glib::ustring& domain, int code, const Glib::ustring& message), g_dbus_method_invocation_return_error_literal)
 
 #m4 _CONVERSION(`const Glib::Error&', `const GError*', `$3.gobj()')
-  _WRAP_METHOD(void return_gerror(const Glib::Error& error), g_dbus_method_invocation_return_gerror)
+  _WRAP_METHOD(void return_error(const Glib::Error& error), g_dbus_method_invocation_return_gerror)
 
   _WRAP_METHOD(void return_dbus_error(const Glib::ustring& error_name, const Glib::ustring& error_message), g_dbus_method_invocation_return_dbus_error)
 
diff --git a/glib/src/variant.ccg b/glib/src/variant.ccg
index eaa4829..5b47bf9 100644
--- a/glib/src/variant.ccg
+++ b/glib/src/variant.ccg
@@ -103,6 +103,15 @@ VariantContainerBase::create_tuple(const std::vector<VariantBase>& children)
   return result;
 }
 
+//static
+VariantContainerBase
+VariantContainerBase::create_tuple(const VariantBase& child)
+{
+  std::vector<VariantBase> vec;
+  vec.push_back(child);
+  return create_tuple(vec);
+}
+
 void VariantContainerBase::get_child(VariantBase& child, gsize index) const
 {
   if(index >= g_variant_n_children(gobject_))
diff --git a/glib/src/variant.hg b/glib/src/variant.hg
index 83d8b08..89fcba0 100644
--- a/glib/src/variant.hg
+++ b/glib/src/variant.hg
@@ -277,6 +277,12 @@ public:
    */
   static VariantContainerBase create_tuple(const std::vector<VariantBase>& children);
 
+  /** Create a tuple variant with a single variant child.
+   * @param child The child variant.
+   * @return The newly created tuple variant (as a VariantContainerBase).
+   */
+  static VariantContainerBase create_tuple(const VariantBase& child);
+
   _WRAP_METHOD(gsize get_n_children() const, g_variant_n_children)
 
   /** Reads a child item out of this instance. This method is valid for
diff --git a/tools/m4/convert_gio.m4 b/tools/m4/convert_gio.m4
index 67acbce..6da976b 100644
--- a/tools/m4/convert_gio.m4
+++ b/tools/m4/convert_gio.m4
@@ -192,6 +192,7 @@ _CONVERSION(`const Glib::RefPtr<SettingsBackend>&',`GSettingsBackend*',__CONVERT
 _CONVERSION(`GVariant*',`VariantBase',`Glib::wrap($3, true)')
 _CONVERSION(`GVariant*',`Glib::VariantContainerBase',`Glib::VariantContainerBase($3, false)')
 _CONVERSION(`const Glib::VariantBase&',`GVariant*',`const_cast<GVariant*>(($3).gobj())')
+_CONVERSION(`const Glib::VariantContainerBase&',`GVariant*',`const_cast<GVariant*>(($3).gobj())')
 
 #Socket
 _CONVERSION(`const Glib::RefPtr<Socket>&',`GSocket*',__CONVERT_CONST_REFPTR_TO_P)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]