如何获得g_dbus_connection_signal_subscribe函数来告诉我有关预先存在的对象/接口的信息?

如何获得g_dbus_connection_signal_subscribe函数来告诉我有关预先存在的对象/接口的信息?,c,dbus,bluez,gdbus,C,Dbus,Bluez,Gdbus,函数g_dbus_connection_signal_subscribe非常适用于告诉我新dbus对象何时出现(或消失)以及InterfacesAdded signal(或InterfacesRemoved signal)。但我需要了解预先存在的对象/接口 我编写了下面的C代码,以便在总线上添加/删除DBus对象时提供回调。为了简单起见,省略了错误检查 #include <stdio.h> #include <stdlib.h> #include <gio/gio.

函数g_dbus_connection_signal_subscribe非常适用于告诉我新dbus对象何时出现(或消失)以及InterfacesAdded signal(或InterfacesRemoved signal)。但我需要了解预先存在的对象/接口

我编写了下面的C代码,以便在总线上添加/删除DBus对象时提供回调。为了简单起见,省略了错误检查

#include <stdio.h>
#include <stdlib.h>
#include <gio/gio.h>

static void signal_cb(GDBusConnection *connection,
        const gchar *sender_name,const gchar *object_path,
        const gchar *interface_name,const gchar *signal_name,
        GVariant *parameters,gpointer user_data)
{
    printf("%s: %s.%s %s\n",object_path,interface_name,signal_name,
        g_variant_print(parameters,TRUE));
}

int main(int argc,char *argv[])
{
GDBusConnection *c;
GMainLoop *loop;
int filter_id;

    c = g_bus_get_sync(G_BUS_TYPE_SYSTEM,NULL,&err);
    loop = g_main_loop_new(NULL,0);
    filter_id = g_dbus_connection_signal_subscribe(c,
        "org.bluez",NULL,NULL,NULL,NULL,
        G_DBUS_SIGNAL_FLAGS_NONE,signal_cb,NULL,NULL);   
    g_main_loop_run (loop);
    g_main_loop_unref (loop);

    exit(0);
}
#包括
#包括
#包括
静态无效信号_cb(GDBUS连接*连接,
常量gchar*发送方名称,常量gchar*对象路径,
常量gchar*接口名称,常量gchar*信号名称,
GVariant*参数,gpointer用户(U数据)
{
printf(“%s:%s.%s%s\n”),对象路径、接口名称、信号名称,
g_变量_打印(参数,真));
}
int main(int argc,char*argv[])
{
GDBUS连接*c;
GMainLoop*循环;
int filter_id;
c=g_总线获取同步(g_总线类型系统,空,错误(&err));
loop=g_main_loop_new(NULL,0);
filter_id=g_dbus_connection_signal_subscribe(c,
“org.bluez”,空,空,空,空,
G_DBUS_信号_标志_无,信号_cb,NULL,NULL);
g_主循环运行(循环);
g_主回路_unref(回路);
出口(0);
}
所以我要做的是跟踪树的org.bluez分支下存在的所有DBus对象。(这些表示可插拔蓝牙控制器和每个控制器发现的设备)。我需要知道程序启动前已经存在的DBus对象,以及程序启动后出现的新对象

上面的代码告诉了我关于新对象的信息,但没有告诉我关于已经存在的对象的信息。gdbus API中是否有方法为已经存在的对象获取“InterfacesCreated”信号?我想我可以读取整个DBus对象层次结构,然后订阅更改,但这会导致竞争条件,如果在我读取对象层次结构和订阅之间出现对象,那么我将错过这些对象


使用gdbus API实现这一点的最佳实践方法是什么?

如Parthiban所述,如果有人遇到这种情况,解决方案(对于实现
org.freedesktop.DBus.ObjectManager
接口的D-Bus服务,如BlueZ)是调用
GetManagedObjects
方法。使用GDBus用C编写代码是非常痛苦的,因为它需要详细了解
GVariant
类型;看。另请查看关于
GVariant
数据类型字符串的。但这是如何做到的:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

#include <gio/gio.h>


/* The GVariant must be of type "a{sa{sv}}" (array of interfaces, where each */
/* interface has an array of properties). */
/* This type what DBus provides with InterfacesAdded signal and is also */
/* part of the return value from the GetManagedObjects method. */
static void proc_interface_var(const gchar *objpath,GVariant *iflist)
{
GVariantIter *iter,*iter2;
gchar *ifname,*propname,*proptext;
GVariant *propvalue;

    g_variant_get(iflist,"a{sa{sv}}",&iter);
    while (g_variant_iter_loop(iter,"{sa{sv}}",&ifname,&iter2)) {
        if (strcmp(ifname,"org.bluez.Adatper1") != 0 &&
                                    strcmp(ifname,"org.bluez.Device1") != 0) {
            /* we only care about the Adatper1 and Device1 interfaces */
            continue;
        } /* if */
        printf("Interface %s added to object %s\n",ifname,objpath);
        while (g_variant_iter_loop(iter2,"{sv}",&propname,&propvalue)) {
            proptext = g_variant_print(propvalue,0);
            printf("\t%s=%s\n",propname,proptext);
            g_free(proptext);
        } /* while */
    } /* while */
    return;
} /* proc_interface_var */


/* The GVariant must be of type "a{sv}" (an array of properties). */
static void proc_property_var(const gchar *objpath,
                                        gchar *ifname,GVariant *proplist)
{
GVariantIter *iter;
gchar *propname,*proptext;
GVariant *propvalue;

    g_variant_get(proplist,"a{sv}",&iter);
    while (g_variant_iter_loop(iter,"{sv}",&propname,&propvalue)) {
        proptext = g_variant_print(propvalue,0);
        printf("\tProperty changed on object %s interface %s: %s=%s\n",
            objpath,ifname,propname,proptext);
        g_free(proptext);
    } /* while */
    return;
} /* proc_property_var */


static void signal_cb(GDBusConnection *c,
            const gchar *sender_name,const gchar *object_path,
            const gchar *interface_name,const gchar *signal_name,
            GVariant *parameters,gpointer user_data)
{
char fullsignal[200];
gchar *s,*objpath,*ifname,*propname,*proptext;
GVariant *ifvar,*propvalue;
GVariantIter *iter,*iter2;

    snprintf(fullsignal,200,"%s.%s",interface_name,signal_name);
    if (strcmp(fullsignal,
                "org.freedesktop.DBus.ObjectManager.InterfacesAdded") == 0) {
        g_variant_get(parameters,"(o*)",&objpath,&ifvar);
        proc_interface_var(objpath,ifvar);
    } else if (strcmp(fullsignal,
                "org.freedesktop.DBus.Properties.PropertiesChanged") == 0) {
        g_variant_get(parameters,"(s*as)",&ifname,&propvalue,&iter2);
        proc_property_var(object_path,ifname,propvalue);
        while (g_variant_iter_loop(iter2,"s",&propname)) {
            printf("\tProperty changed on object %s interface %s: "
                "%s is nil\n",object_path,ifname,propname);
        } /* while */
    } else {
        printf("Ignoring unsupported signal for object %s, "
            "signal=%s.%s, param type=%s\n",
            object_path,interface_name,signal_name,
            g_variant_get_type_string(parameters));
        s = g_variant_print(parameters,TRUE);
        printf("Unsupported signal: parameters %s\n",s);
        g_free(s);
    } /* else */

    return;
} /* signal_cb */


static void bt_discover(GDBusConnection *c,const char *ctlname,int on_off)
{
GError *err=NULL;
GVariant *result;
const char *method;
char ctlpath[80];

    snprintf(ctlpath,80,"/org/bluez/%s",ctlname);
    method = on_off ? "StartDiscovery" : "StopDiscovery";
    result = g_dbus_connection_call_sync(c,"org.bluez",ctlpath,
        "org.bluez.Adapter1",method,NULL,
        G_VARIANT_TYPE("()"),       /* return-type */
        G_DBUS_CALL_FLAGS_NONE,5000,NULL,&err);
    if (result==NULL) {
        if (err) fprintf(stderr,"g_dbus_connection_call error: %s\n",   
            err->message);
        exit(1);
    } /* if */
    g_variant_unref(result);
    return;
} /* bt_discover */


static void *receive_dbus_signals(void *arg)
{
GMainLoop *loop;

    printf("Receiving DBus signals...\n");
    loop = g_main_loop_new(NULL,0);
    g_main_loop_run(loop);
    g_main_loop_unref(loop);
    return NULL;
} /* receive_dbus_signals */


int main(int argc,char *argv[])
{
GError *err=NULL;
GVariant *result,*ifvar;
GVariantIter *iter;
GDBusConnection *c;
GDBusNodeInfo *node;
gchar *objpath;
pthread_t handle;
int filter_id;

    if ((c = g_bus_get_sync(G_BUS_TYPE_SYSTEM,NULL,&err)) == NULL) {
        if (err) fprintf(stderr,"g_bus_get error: %s\n",err->message);
        exit(1);
    } /* if */

    filter_id = g_dbus_connection_signal_subscribe(c,
        "org.bluez",NULL,NULL,NULL,NULL,
        G_DBUS_SIGNAL_FLAGS_NONE,signal_cb,NULL,NULL);
    if (pthread_create(&handle,NULL,receive_dbus_signals,NULL) != 0) {
        fprintf(stderr,"Failed to create DBus listen thread\n");
        exit(1);
    } /* if */

    result = g_dbus_connection_call_sync(c,"org.bluez","/",
        "org.freedesktop.DBus.ObjectManager","GetManagedObjects",NULL,
        G_VARIANT_TYPE("(a{oa{sa{sv}}})"),      /* return-type */
        G_DBUS_CALL_FLAGS_NONE,5000,NULL,&err);
    if (result==NULL) {
        if (err) fprintf(stderr,"g_dbus_connection_call error: %s\n",   
            err->message);
        exit(1);
    } /* if */

    g_variant_get(result,"(a{oa{sa{sv}}})",&iter);
    /* below we replace 'a{sa{sv}}' with '*' to get it as a GVariant */
    while (g_variant_iter_loop(iter,"{o*}",&objpath,&ifvar)) {
        proc_interface_var(objpath,ifvar);
    } /* while */
    g_variant_unref(result);

    bt_discover(c,"hci0",1);
    sleep(5);
    bt_discover(c,"hci0",0);
    sleep(5);

    exit(0);
}
#包括
#包括
#包括
#包括
#包括
/*GVariant的类型必须为“a{sa{sv}”(接口数组,其中*/
/*接口有一个属性数组)*/
/*这种类型是DBus提供的接口附加信号,也是*/
/*GetManagedObjects方法返回值的一部分*/
静态无效过程接口变量(常量gchar*objpath,GVariant*iflist)
{
GVariantIter*iter,*iter2;
gchar*ifname、*propname、*proptext;
GVariant*propvalue;
g_variant_get(iflist,“a{sa{sv}}”,和iter);
while(g_variant_iter_loop(iter,{sa{sv}}},&ifname,&iter2)){
if(strcmp(ifname,“org.bluez.Adatper1”)!=0&&
strcmp(ifname,“org.bluez.Device1”)!=0{
/*我们只关心Adatper1和Device1接口*/
继续;
}/*如果*/
printf(“接口%s添加到对象%s\n”,ifname,objpath);
while(g_variant_iter_loop(iter2,{sv},&propname,&propvalue)){
proptext=g_变量_打印(propvalue,0);
printf(“\t%s=%s\n”,propname,proptext);
g_free(proptext);
}/*当*/
}/*当*/
返回;
}/*过程接口变量*/
/*GVariant必须是“a{sv}”(属性数组)类型*/
静态无效过程属性变量(常量gchar*objpath,
gchar*ifname,GVariant*proplist)
{
GVariantIter*iter;
gchar*propname,*proptext;
GVariant*propvalue;
g_variant_get(proplist,a{sv},&iter);
while(g_variant_iter_loop(iter,{sv},&propname,&propvalue)){
proptext=g_变量_打印(propvalue,0);
printf(“\t对象%s接口%s上的属性已更改:%s=%s\n”,
objpath、ifname、propname、proptext);
g_free(proptext);
}/*当*/
返回;
}/*过程属性变量*/
静态无效信号_cb(GDBUS连接*c,
常量gchar*发送方名称,常量gchar*对象路径,
常量gchar*接口名称,常量gchar*信号名称,
GVariant*参数,gpointer用户(U数据)
{
字符全信号[200];
gchar*s、*objpath、*ifname、*propname、*proptext;
GVariant*ifvar,*propvalue;
GVariantIter*iter,*iter2;
snprintf(全信号,200,“%s.%s”,接口名称,信号名称);
如果(strcmp)(全信号,
“org.freedesktop.DBus.ObjectManager.InterfacesAdded”)==0){
g_variant_get(参数,“(o*)”、&objpath和&ifvar);
过程接口变量(objpath,ifvar);
}否则,如果(strcmp)(全信号,
“org.freedesktop.DBus.Properties.PropertiesChanged”)==0){
g_variant_get(参数,“(s*as)”,&ifname,&propvalue,&iter2);
过程属性变量(对象路径、ifname、propvalue);
while(g_变体_iter_循环(iter2,“s”和propname)){
printf(“\t对象%s接口%s上的属性已更改:”
“%s为nil\n”,对象\u路径、ifname、propname);
}/*当*/
}否则{
printf(“忽略对象%s不支持的信号,”
“信号=%s.%s,参数类型=%s\n”,
对象路径、接口名称、信号名称、,
g_变量_获取_类型_字符串(参数));
s=g_变量_打印(参数,真);
printf(“不支持的信号:参数%s\n”,s);
g_free(s);
}/*其他*/
返回;
}/*信号灯*/
静态无效bt_发现(GDBUS连接