我正在学习如何在C上使用D-Bus和GLib。到目前为止,我已经创建了一个调用我的应用程序的D-Bus服务,并在使用'dbus-send'命令后得到响应。我有两个文件,一个带有D-Bus代码,另一个带有要调用的功能。 'test_method_start'函数让我们知道它已成功调用,并创建一个新线程。第二个功能告诉我们,我们正在停止,并退出线程。
我显然遗漏了一些东西,因为我没有看到函数调用的结果。谁能告诉我哪里出错了?我指的是示例here。
以下是代码段:
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
我的命令行语句是:
dbus-send --session --print-reply --type = method_call --dest = org.test.DBusClient / org / test / DBusObject org.test.DBusClientInterface.test_method_start string:“Hello”
,回复是:
方法return sender =:1.364 - &gt; dest =:1.376 reply_serial = 2 字符串“你跟'你好'打招呼。谢谢!”
现在我应该做些什么才能让“test_method_start”运行?
感谢您的帮助。
答案 0 :(得分:1)
您不应该在未启动的主题上调用pthread_exit
。 test_method_start
由其他人创建的线程调用。
如果您从未在任何地方打电话或取其地址,您期望如何调用test_method_start
? DBUS没有魔力;如果要调用它,则必须从handle_method_call
调用它。您似乎有代码来检查方法名称是否为“test_method_start”,因此您可以在if
内调用它。