1

我在尝试注册以使用gdbusC 中的库从 wpa_supplicant 的 p2p dbus 接口接收“InvitationReceived”信号时遇到问题。

我可以很好地创建到 P2P dbus 接口的代理连接并在其上调用方法,但是当我尝试将信号处理程序连接到代理时,我只是收到以下错误消息,指出信号无效(代码中的相关输出样本):

(进程:6764):GLib-GObject-WARNING **:/tmp/buildd/glib2.0-2.42.1/./gobject/gsignal.c:2461:信号'InvitationReceived'对于类型的实例'0x909ae0'无效'GDBusProxy'

这很奇怪,因为“InvitationReceived”是wpa_supplicant dbus api定义的信号名称。


代码示例:

static void on_wpa_ready (GObject *source_object,
                          GAsyncResult *res,
                          gpointer user_data) {
    g_print("on_wpa_ready\n");

    GError *error = NULL;
    GVariant *output;  

    GDBusProxy *p2p_proxy = g_dbus_proxy_new_for_bus_finish(res, &error);
    if (error) {
        g_print("proxy finish error: %s\n", error->message);
        g_error_free(error);
        return;
    }

    /* call p2p_listen */   
    g_clear_error(&error);
    output = NULL;
    output = g_dbus_proxy_call_sync(p2p_proxy,
                      "Listen",
                      g_variant_new("(i)", 0), //params
                      G_DBUS_CALL_FLAGS_NONE,
                      10, //timeout_msec
                      NULL,
                      &error
    );

    if (error) {
        g_print("Listen call error: %s\n", error->message);
        g_error_free(error);
        g_print("continuing...\n");
    }
    else {
        /* it gets to this print stmt, so the method was able to be called */
        g_print("Listen successful\n");
    }

    /* register for signal from p2p device */
    /* THIS IS WHERE THE ERROR IS */
    error = NULL;
    g_signal_connect(p2p_proxy,
                     "InvitationReceived",
                     G_CALLBACK(on_signal), // stub func that does something simple
                     NULL);

}

int main (int argc, char **argv) {
    GMainLoop *loop;

    /* connect to wpa_supplicant p2p dbus interface */
    g_dbus_proxy_new_for_bus(G_BUS_TYPE_SYSTEM,
                     G_DBUS_PROXY_FLAGS_NONE,
                     NULL,
                     "fi.w1.wpa_supplicant1", //name,
                     "/fi/w1/wpa_supplicant1/Interfaces/0", //object_path,
                     "fi.w1.wpa_supplicant1.Interface.P2PDevice", //interface_name,
                     NULL,
                     on_wpa_ready, //callback,
                     NULL);
    );

    loop = g_main_loop_new(NULL, FALSE);
    g_main_loop_run(loop);
}

是否有一些特殊的路径需要附加到信号名称中?还是我应该使用与用于调用方法的代理不同的代理来注册信号处理程序?

4

1 回答 1

0

(终于找到了问题/解决方案——在这里为未来的 gdbus 用户发布)


来自GDBusProxy 的 GIO 文档

通用的“g-properties-changed”和“g-signal”信号使用起来不太方便。因此,推荐使用代理的方式是继承 GDBusProxy,并在派生类中拥有更自然的属性和信号。


正如本段所暗示的,事实证明,基GDBusProxy类只支持所有接口都保证具有的两个通用信号:g-properties-changedg-signal每当给定代理的对象发出任何信号时,在代理上注册g-signal信号都会调用回调,包括我在这种情况下碰巧正在寻找的那个。

我最终没有使用文档中建议的子类化路线,而是使用了一个快速而肮脏的包罗万象的处理程序:

// the new snippet for connecting a signal handler:
g_signal_connect(p2p_proxy,
                 "g-signal",
                 G_CALLBACK(on_signal), // stub func that does something simple
                 NULL);

然后检查回调函数中实际调用了哪个信号:

/* callback function */
static void on_signal (GDBusProxy *proxy,
                       gchar *sender_name,
                       gchar *signal_name,
                       GVariant *params,
                       gpointer user_data) {
    if (g_strcmp0(signal_name, "InvitationReceived")) {
        // ignore all irrelevant signals
        return;
    } 

    g_print("InvitationReceived signal received\n");

    /* other handling code.... */
}
于 2016-04-14T21:14:17.047 回答