I'm learning how to use D-Bus on C with GLib. So far I've created a D-Bus service which calls my application, and I get a response after using the 'dbus-send' command. I have two files, one with the D-Bus code and one with the functions to call. The 'test_method_start' function lets us know that it has been called successfully, and creates a new thread. The second funtion tells us that we are stopping, and exits the thread.
I'm obviously missing something out, because I'm not seeing the result of the function calls. Can anyone tell me where I'm going wrong? I'm referring to the example here.
Here's the code snippets:
File1.c:
void test_method_start()
{
printf("Test method started\n")``;
//syslog(LOG_NOTICE, "Test method started\n");
if (!(pthread_create(&socketServerThread, NULL,
socketServerLoop, &socketServerParam)))
{
printf("Socket Server thread created successfully\n");
}
else
fprintf(stderr, "Error creating Socket Server thread\n");
pthread_exit(NULL);
}
void test_method_stop()
{
printf("Test method ended\n");
pthread_exit(NULL);
}
File2.c:
/*
* dbusClient
*/
/** Headers **/
#include "dbusClient.h"
#include <glib.h>
#include <gio/gio.h>
#include <gio/gioerror.h>
#include <gio/gdbuserror.h>
#include <stdlib.h>
#include <stdio.h>
/** Function Predeclarations **/
/** Globals **/
/** The service name on the bus. **/
static const gchar service[] = "org.test.DBusClient";
/** The object we publish on the bus. **/
static const gchar object_path[] = "/org/test/DBusObject";
/** Introspection data for the one object, in the internal form. **/
static GDBusNodeInfo *introspection_data = NULL;
/** Introspection data for the one object in XML form **/
static const gchar introspection_xml[] =
"<node>"
" <interface name='org.test.DBusClientInterface'>"
" <method name='test_method_start'>"
" <arg type='s' name='message' direction='in'/>"
" <arg type='s' name='response' direction='out'/>"
" </method>"
" <method name='test_method_stop'>"
" <arg type='s' name='message' direction='in'/>"
" <arg type='s' name='response' direction='out'/>"
" </method>"
" </interface>"
"</node>";
/** Object Callbacks **/
/* Handle a request for a property */
static GVariant *handle_get_property (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *property_name,
GError **error,
gpointer user_data)
{
printf("handle_get_property\n");
/* Print an optional log message */
#ifdef VERBOSE
fprintf (stderr, "[server 0] "
"handle_get_property (%p,\"%s\",\"%s\",\"%s\",\"%s\",(error),%p)\n",
connection, sender, object_path, interface_name, property_name,
user_data);
#endif
/* We currently don't have any properties,
so this should be an error. */
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_FAILED,
"[server 0] Invalid property '%s'",
property_name);
// And we're done
return NULL;
} // handle_get_property
/* Handle a call to a method */
static void handle_method_call (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *method_name,
GVariant *parameters,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
printf("handle_method_call\n");
#ifdef VERBOSE
gchar *paramstr = g_variant_print (parameters, TRUE);
fprintf (stderr, "[server 0] "
"handle_method_call (%p,\"%s\",\"%s\",\"%s\",\"%s",
\"\",invocation),%p)\n",
connection, sender, object_path, interface_name, method_name,
paramstr, user_data);
g_free (paramstr);
#endif
/* Default: No such method */
if (g_strcmp0 (method_name, "test_method_start") == 0)
{
const gchar *greeting;
g_variant_get (parameters, "(&s)", &greeting);
if (g_strcmp0 (greeting, "Return Unregistered") == 0)
{
g_dbus_method_invocation_return_error (invocation,
G_IO_ERROR,
G_IO_ERROR_FAILED_HANDLED,
"As requested, here's a GError not registered
(G_IO_ERROR_FAILED_HANDLED)");
}
else if (g_strcmp0 (greeting, "Return Registered") == 0)
{
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_MATCH_RULE_NOT_FOUND,
"As requested, here's a GError that is
registered
(G_DBUS_ERROR_MATCH_RULE_NOT_FOUND)");
}
else if (g_strcmp0 (greeting, "Return Raw") == 0)
{
g_dbus_method_invocation_return_dbus_error (invocation,
"org.gtk.GDBus.SomeErrorName",
"As requested, here's a raw D-Bus error");
}
else
{
gchar *response;
response = g_strdup_printf ("You greeted me with '%s'.
Thanks!", greeting);
g_dbus_method_invocation_return_value
(invocation,
g_variant_new ("(s)", response));
g_free (response);
}
}
else if (g_strcmp0 (method_name, "test_method_stop") == 0)
{
const gchar *greeting;
g_variant_get (parameters, "(&s)", &greeting);
if (g_strcmp0 (greeting, "Return Unregistered") == 0)
{
g_dbus_method_invocation_return_error (invocation,
G_IO_ERROR,
G_IO_ERROR_FAILED_HANDLED,
"As requested, here's a GError not registered
(G_IO_ERROR_FAILED_HANDLED)");
}
else if (g_strcmp0 (greeting, "Return Registered") == 0)
{
g_dbus_method_invocation_return_error (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_MATCH_RULE_NOT_FOUND,
"As requested, here's a GError that is registered
(G_DBUS_ERROR_MATCH_RULE_NOT_FOUND)");
}
else if (g_strcmp0 (greeting, "Return Raw") == 0)
{
g_dbus_method_invocation_return_dbus_error (invocation,
"org.gtk.GDBus.SomeErrorName",
"As requested, here's a raw D-Bus error");
}
else
{
gchar *response;
response = g_strdup_printf ("You greeted me with
'%s'.Thanks!", greeting);
g_dbus_method_invocation_return_value (invocation,
g_variant_new ("(s)", response));
g_free (response);
}
}
else
{
g_dbus_method_invocation_return_error (invocation,
G_IO_ERROR,
G_IO_ERROR_INVALID_ARGUMENT,
"[server 0] Invalid method: '%s'",
method_name);
}
} // handle_method_call
/* Handle a request to set a property. */
static gboolean handle_set_property (GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *property_name,
GVariant *value,
GError **error,
gpointer user_data)
{
printf("handle_set_property\n");
/* Print an optional log message */
#ifdef VERBOSE
gchar *valstr = g_variant_print (value, TRUE);
fprintf (stderr, "[server 0] "
"handle_set_property (%p,\"%s\",\"%s\",\"%s\",\"%s\",
\"%s\",(error),%p)\n",
connection, sender, object_path,
interface_name, property_name,
valstr, user_data);
g_free (valstr);
#endif
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_FAILED,
"[server 0] No such property: '%s'",
property_name);
return 0;
} // handle_set_property
/** Bus Callbacks **/
/* When the bus gets acquired... */
static void on_bus_acquired (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
printf("on_bus_acquired\n");
static GDBusInterfaceVTable interface_vtable =
{
handle_method_call,
handle_get_property,
handle_set_property
};
guint registration_id;
// GError *error = NULL;
// An optional notification
#ifdef VERBOSE
fprintf (stderr, "[server 0] on_bus_acquired (%p, \"%s\", %p)\n",
connection, name, user_data);
#endif
registration_id = g_dbus_connection_register_object (connection,
object_path,
introspection_data->interfaces[0],
&interface_vtable,
NULL, // Optional user data
NULL, // Func. for freeing user data
NULL); // GError
// Check to see whether or not the call succeeded.
printf("g_assert registration_id = %d\n", registration_id);
g_assert (registration_id > 0);
} // on_bus_acquired
static void on_name_acquired (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
// An optional notification
#ifdef VERBOSE
fprintf (stderr, "[server 0] on_name_acquired (%p, \"%s\", %p)\n",
connection, name, user_data);
#endif
} // on_name_acquired
static void on_name_lost (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
// An optional notification
#ifdef VERBOSE
fprintf (stderr, "[server 0] on_name_lost (%p, \"%s\", %p)\n",
connection, name, user_data);
#endif
// Things seem to have gone badly wrong, so give up
exit (1);
} // on_name_lost
/** Main **/
void *dbusLoop(void *dbusParam)
{
guint owner_id;
GMainLoop *loop;
printf("Reached dbusLoop\n");
// Build an internal representation of the interface
printf("Register the object\n");
introspection_data = g_dbus_node_info_new_for_xml
(introspection_xml, NULL);
g_assert (introspection_data != NULL);
// Request the name on the bus
owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
service,
G_BUS_NAME_OWNER_FLAGS_NONE,
on_bus_acquired,
on_name_acquired,
on_name_lost,
NULL,
NULL);
// Start the main loop
printf("Start the loop\n");
loop = g_main_loop_new (NULL, FALSE);
g_main_loop_run (loop);
// Tell the bus that we're done with the name
printf("Release the owner_id\n");
g_bus_unown_name (owner_id);
// Clean up after ourselves
g_dbus_node_info_unref (introspection_data);
//Exit and join main thread
pthread_exit(NULL);
} // main
My command line statement is:
dbus-send --session --print-reply --type=method_call --dest=org.test.DBusClient /org/test/DBusObject org.test.DBusClientInterface.test_method_start string:"Hello"
and the response is:
method return sender=:1.364 -> dest=:1.376 reply_serial=2 string "You greeted me with 'Hello'. Thanks!"
What should I be doing now to get "test_method_start" to run?
Thanks for any help.