c - 发出 dbus-send 命令后,如何使用 C 调用方法?

标签 c glib dbus

我正在学习如何通过 GLib 在 C 上使用 D-Bus。到目前为止,我已经创建了一个调用我的应用程序的 D-Bus 服务,并且在使用“dbus-send”命令后收到了响应。我有两个文件,一个包含 D-Bus 代码,另一个包含要调用的函数。 “test_method_start”函数让我们知道它已被成功调用,并创建一个新线程。第二个函数告诉我们正在停止,并退出线程。

我显然错过了一些东西,因为我没有看到函数调用的结果。谁能告诉我哪里错了?我指的是示例 here .

这是代码片段:

文件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"

响应是:

method return sender=:1.364 -> dest=:1.376 reply_serial=2 string "You greeted me with 'Hello'. Thanks!"

我现在应该做什么才能让“test_method_start”运行?

感谢您的帮助。

最佳答案

您不应在未启动的线程上调用 pthread_exittest_method_start 由其他人创建的线程调用。

当您从未在任何地方调用它或获取其地址时,您如何期望调用 test_method_start ? DBUS 并没有什么魔力;如果您希望调用它,则必须从 handle_method_call 调用它。您似乎有代码来检查方法名称是否为“test_method_start”,因此您可以在 if 内调用它。

关于c - 发出 dbus-send 命令后,如何使用 C 调用方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32457019/

相关文章:

c++ - 字符串到字节数组

c - 为什么不增加?

gnome:如何在屏幕保护程序激活时执行命令?

python - 简单(但具体)的监听器和发送器 Python 3 DBus 示例

python - 使用 Python-dbus 在 dbus 上发射信号

c - 在 Function 中使用 malloc 时出错

c++ - 为什么 volatile 在多线程 C 或 C++ 编程中没有用?

c - 了解 C 语言中的宏和预处理器指令

string - 如何使用 vala/genie 获取今天的日期并将其转换为字符串?

c - 如何选择要使用 GLib 测试套件运行的测试?