Search code examples
clinuxdictionarydbusbluez

How to create Dict of {String, Variant} for D-Bus method?


I'm trying to call D-Bus method, but don't understand how to add needed args.

  • Method name: CreateSession (String destination, Dict of {String, Variant} args) ↦ (Object Path session)
  • Bus Name: org.bluez.obex
  • Object Path: /org/bluez/obex
  • Interface: org.bluez.obex.Client1

I successfully can call this method in D-Feet app with this arguments:

"D0:9C:7A:A1:A4:63",{'Target':GLib.Variant('s','OPP')}

But how make the same using only dbus.h?

Here's my code:

// Do before compile sudo apt-get install -y libdbus-1-dev
// gcc -o test -Wall test.c `pkg-config --cflags dbus-1` `pkg-config --libs dbus-1`
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dbus/dbus.h>
 
int main() {
    DBusConnection *sesBusCon;
    DBusError error;
    DBusMessage *call;
    DBusMessage *reply;

    dbus_error_init(&error);
    if (dbus_error_is_set(&error)) {
        fprintf(stderr, "%s", error.message);
        return 1;
    }
    
    sesBusCon = dbus_bus_get(DBUS_BUS_SESSION, &error);
    if (dbus_error_is_set(&error)) {
        fprintf(stderr, "%s", error.message);
        return 1;
    }
    
    call = dbus_message_new_method_call("org.bluez.obex", "/org/bluez/obex", "org.bluez.obex.Client1", "CreateSession");     
    
    reply = dbus_connection_send_with_reply_and_block (sesBusCon, call, 100000, &error);
    if (dbus_error_is_set(&error)) {
        fprintf(stderr, "%s", error.message);
        return 1;
    }
    
    return 0;
}

Solution

  • Maybe it helps someone:

    // Do before compile sudo apt-get install -y libdbus-1-dev
    // gcc -o test -Wall test.c `pkg-config --cflags dbus-1` `pkg-config --libs dbus-1`
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <dbus/dbus.h>
     
    int main() {
        DBusConnection *sesBusCon;
        DBusError error;
        DBusMessage *call;
        DBusMessage *reply;
        DBusMessageIter iterInit, iterDict, iterEntry, iterValue;
    
        dbus_error_init(&error);
        if (dbus_error_is_set(&error)) {
            fprintf(stderr, "%s", error.message);
            return 1;
        }
        
        sesBusCon = dbus_bus_get(DBUS_BUS_SESSION, &error);
        if (dbus_error_is_set(&error)) {
            fprintf(stderr, "%s", error.message);
            return 1;
        }
        
        call = dbus_message_new_method_call("org.bluez.obex", "/org/bluez/obex", "org.bluez.obex.Client1", "CreateSession");
    
        char *destination = "D0:9C:7A:A1:A4:63";
        dbus_message_append_args(call, DBUS_TYPE_STRING, &destination, DBUS_TYPE_INVALID);
        
        dbus_message_iter_init_append(call, &iterInit);
        dbus_message_iter_open_container(&iterInit, DBUS_TYPE_ARRAY,
        DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
        DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
        DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &iterDict);
        
            dbus_message_iter_open_container(&iterDict, DBUS_TYPE_DICT_ENTRY, NULL, &iterEntry);
            char *key = "Target";
            dbus_message_iter_append_basic(&iterEntry, DBUS_TYPE_STRING, &key);
            dbus_message_iter_open_container(&iterEntry, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &iterValue);
            void *val = "OPP";
            dbus_message_iter_append_basic(&iterValue, DBUS_TYPE_STRING, &val);
            dbus_message_iter_close_container(&iterEntry, &iterValue);
            dbus_message_iter_close_container(&iterDict, &iterEntry);
        
        dbus_message_iter_close_container(&iterInit, &iterDict);
        
        DBusPendingCall* replyPending;
        DBusMessage* replyMessage;
        DBusMessageIter replyIter;
        
        dbus_connection_send_with_reply(sesBusCon, call, &replyPending, -1);
        dbus_pending_call_block(replyPending);
        
        if (dbus_pending_call_get_completed (replyPending))
        {
            replyMessage = dbus_pending_call_steal_reply(replyPending);
            dbus_message_iter_init(replyMessage, &replyIter);
            char *objectPath;
            dbus_message_iter_get_basic(&replyIter, &objectPath);
            printf("object path %s \n",objectPath);
        }
        
        
        return 0;
    }