在发出 dbus-send 命令后,如何使用 C 调用方法?
Posted
技术标签:
【中文标题】在发出 dbus-send 命令后,如何使用 C 调用方法?【英文标题】:How does a method get called using C, after the dbus-send command is issued? 【发布时间】:2015-12-04 02:13:25 【问题描述】:我正在学习如何通过 GLib 在 C 上使用 D-Bus。到目前为止,我已经创建了一个调用我的应用程序的 D-Bus 服务,并且在使用“dbus-send”命令后我得到了响应。我有两个文件,一个是 D-Bus 代码,一个是要调用的函数。 'test_method_start' 函数让我们知道它已被成功调用,并创建了一个新线程。第二个函数告诉我们我们正在停止,并退出线程。
我显然遗漏了一些东西,因为我没有看到函数调用的结果。谁能告诉我哪里出错了?我指的是here的例子。
这里是sn-ps的代码:
文件1.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);
文件2.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"
响应是:
方法返回 sender=:1.364 -> dest=:1.376 reply_serial=2 string "你用‘你好’打招呼。谢谢!”
我现在应该怎么做才能让“test_method_start”运行?
感谢您的帮助。
【问题讨论】:
【参考方案1】:你不应该在你没有启动的线程上调用pthread_exit
。 test_method_start
被其他人创建的线程调用。
当您从未在任何地方呼叫它或获取其地址时,您如何期望test_method_start
被呼叫? DBUS 没有魔力;如果你想调用它,你必须从handle_method_call
调用它。您似乎有检查方法名称是否为“test_method_start”的代码,因此您可以在 if
中调用它。
【讨论】:
您好,感谢您的回复。我没有分享整个代码,因为它是机密的。为 DBUS 创建了一个线程,当 test_method_start 函数运行时,它也应该创建一个线程。我也是线程新手。正如您所建议的,我确实尝试从“if”语句中的“handle_method_call”函数调用该函数,但我没有得到任何输出。因此,我认为还有其他一些机制用于运行该功能。我看过的所有示例都没有显示对请求运行的函数的任何调用。我会再试试你的建议。谢谢!以上是关于在发出 dbus-send 命令后,如何使用 C 调用方法?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 dbus-send 调用 org.bluez.Adapter1.StartDiscovery?