D-BUS 基本使用学习 【low-level C API】

待更新:2021-11-21前更新完成 @qiujunyin

实例代码

#include <dbus/dbus.h>
#include <cstddef>
#include <cstdio>
#include <iostream>
#include <unistd.h>

using namespace std;

void reply_to_method_call(DBusConnection* bus_conn,DBusMessage* bus_msg);

int main(){
    DBusError bus_err;
    DBusConnection* bus_conn;

    //1. DBusError初始化
    dbus_error_init(&bus_err);

    //2. 连接DBUS
    bus_conn = dbus_bus_get(DBUS_BUS_SESSION,&bus_err);
    if (dbus_error_is_set(&bus_err)){
        cout<<"Connection Error : "<<bus_err.message<<endl;
        dbus_error_free(&bus_err);
        exit(1);
    }else if(bus_conn == NULL){
        cout<<"bus_conn is null"<<endl;
        exit(1);
    }

    //3. 设置DBUS名称  or 注册一个BUS NAME
    int ret = dbus_bus_request_name(bus_conn,"test.method.server",DBUS_NAME_FLAG_REPLACE_EXISTING,&bus_err);
    if (dbus_error_is_set(&bus_err)){
        cout<<"Connection Error : "<<bus_err.message<<endl;
        dbus_error_free(&bus_err);
        exit(1);
    }else if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER){
        cout<<"request dbus name return fail"<<endl;
        exit(1);
    }


    //4. 信号发送
    dbus_uint32_t serial = 0; // unique number to associate replies with requests
    DBusMessage* bus_msg;
    DBusMessageIter bus_args;
    void* sigvalue = (void*)("hello qiujunyin");

    //object name / interface name / name of the signal
    bus_msg = dbus_message_new_signal("/test/signal/Object","test.signal.Type","Test");
    if (bus_msg==NULL){
        cout<<"dbus signale message is null"<<endl;
        exit(1);
    }
    // 初始化参数迭代器并append进入signal信息
    dbus_message_iter_init_append(bus_msg,&bus_args);
    if (!dbus_message_iter_append_basic(&bus_args, DBUS_TYPE_STRING, &sigvalue)) {
        cout<<"dbus iter append fail : out of memory"<<endl;
        exit(1);
    }
    //发送signal serial带回其在消息队列中的位置
    if (!dbus_connection_send(bus_conn,bus_msg,&serial)){
        cout<<"dbus send signal fail : out of memory"<<endl;
        exit(1);
    } 
    cout<<"signal serial in mq :"<<serial<<endl;
    dbus_connection_flush(bus_conn);
    dbus_message_unref(bus_msg);


    //5. 同步method_call  dbus_connection_send_with_reply_and_block
    DBusMessage * dbus_reply = nullptr;
    const char * dbus_result = nullptr;
    

    bus_msg = dbus_message_new_method_call("org.freedesktop.DBus","/","org.freedesktop.DBus.Introspectable","Introspect");
    if (bus_msg == NULL){
        cout<<"dbus method call is null"<<endl;
        exit(1);
    }
    // 增加入参:a. dbusMessage绑定迭代器原始操作接口 b. dbus_message_append_args

    // const char *v_STRING = "input args test";
    // if (!dbus_message_append_args(bus_msg,DBUS_TYPE_STRING,&v_STRING,DBUS_TYPE_INVALID)){
    //     cout<<"dbus method call append args failed"<<endl;
    //     exit(1);
    // }

    dbus_reply = ::dbus_connection_send_with_reply_and_block(bus_conn, bus_msg, DBUS_TIMEOUT_USE_DEFAULT, &bus_err); //无限时长阻塞
    if (dbus_reply == NULL){
        //如果有入参,预期此处调用失败,此method call为系统dbus提供返回,无需入参。报错多余入参
        cout<<"dbus method call return fail : "<<bus_err.name<<" "<<bus_err.message<<endl;
        exit(1);
    }
    if (!dbus_message_get_args(dbus_reply,&bus_err,DBUS_TYPE_STRING,&dbus_result,DBUS_TYPE_INVALID)){
        cout<<"dbus method call return parser failed : "<<bus_err.name<<" "<<bus_err.message<<endl;
        exit(1);
    }else{
        cout<<"dbue method call result : "<<dbus_result<<endl;
    }
    dbus_message_unref(bus_msg);
    dbus_message_unref(dbus_reply);

    //6. 异步method_call  : 通过迭代器处理输入输出数据
    // 存在问题:异步下如何通过DBusPendingCall捕获错误信息
    DBusPendingCall* bus_pending;
    DBusMessageIter bus_args2;
    void *param = (void*)("");
    void *stat = new int;

    bus_msg = dbus_message_new_method_call("test.method.server","/test/method/Object","test.method.Type","Method");
    if (bus_msg == NULL){
        cout<<"dbus method call is null"<<endl;\
        exit(1);
    }
    dbus_message_iter_init_append(bus_msg,&bus_args2);
    if (!dbus_message_iter_append_basic(&bus_args2, DBUS_TYPE_STRING, &param)) {
        cout<<"dbus iter append fail : out of memory"<<endl;
        exit(1);
    }
    if (!dbus_connection_send_with_reply(bus_conn, bus_msg, &bus_pending, 1000)) { // -1 is default timeout
        cout<<"dbus send method call : out of memory"<<endl;
        exit(1);
    }
    if (bus_pending==NULL){
        cout<<"dbus method call' Pending is NULL"<<endl;
        exit(1);
    }else{
        cout<<"dbus method call' Pending address : "<<bus_pending<<endl;
    }
    dbus_connection_flush(bus_conn);
    dbus_message_unref(bus_msg);

    dbus_pending_call_block(bus_pending);   //在上述时间限制内,阻塞等待返回数据,去除则完全异步
    bus_msg = dbus_pending_call_steal_reply(bus_pending);   //返回数据转换
    if (bus_msg == NULL) {
        cout<<"dbus method call reply NULL"<<endl;
        exit(1);
    }
    dbus_pending_call_unref(bus_pending);   //释放返回数据的句柄

    if(!dbus_message_iter_init(bus_msg,&bus_args)){
        //获取转换后数据的迭代器
        cout<<"dbus method call reply message has no argument"<<endl;
        exit(1);
    }
    else{
        dbus_message_iter_get_basic(&bus_args, stat);
    }
    cout<<"dbus method call reply value : "<<*((int*)stat)<<endl;
    dbus_message_unref(bus_msg);

    //7. 接受信号
    dbus_error_init(&bus_err);
    dbus_bus_add_match(bus_conn,"type='signal',interface='com.example'",&bus_err); //默认对session dbus也监听了
    dbus_connection_flush(bus_conn);
    if (dbus_error_is_set(&bus_err)){
        cout<<"dbus add match fail : "<<bus_err.message<<endl;
        exit(1);
    }
    while(1){
        //非阻塞监听信号
        dbus_connection_read_write(bus_conn, 0);
        bus_msg = dbus_connection_pop_message(bus_conn);
        if(bus_msg==NULL){
            sleep(1);
            continue;
        }

        //再次过滤
        if(dbus_message_is_signal(bus_msg,"com.example","signal_name")){
            if (!dbus_message_get_args(bus_msg,&bus_err,DBUS_TYPE_STRING,&dbus_result,DBUS_TYPE_INVALID)){
                cout<<"dbus method call return parser failed : "<<bus_err.name<<" "<<bus_err.message<<endl;
                exit(1);
            }
            cout<<"dbus get signal message : "<<dbus_result<<endl;
            break;
        }else{
            // cout<<"dbus message interface : "<<dbus_message_get_interface(bus_msg)<<endl;
            // cout<<"dbus message member : "<<dbus_message_get_member(bus_msg)<<endl;
            cout<<"dbus check signal message and pass this signal"<<endl;
        }
        dbus_message_unref(bus_msg);
    }

    //8. 提供被远程调用的方法
    while(1){
        //非阻塞监听信号
        dbus_connection_read_write(bus_conn, 0);
        bus_msg = dbus_connection_pop_message(bus_conn);
        if(bus_msg==NULL){
            sleep(1);
            continue;
        }

        if(dbus_message_is_method_call(bus_msg,"test.method.Type","Method")){
            reply_to_method_call(bus_conn,bus_msg);
            break;
        }

        dbus_message_unref(bus_msg);
    }

    //9. 通过网络的DBUS方式


    // 释放DBUS连接 (和dbus_connection_close 的区别)
    dbus_connection_unref(bus_conn);
    delete[] (char*)stat;
    cout<<"All succeed"<<endl;
    return 0;
}

void reply_to_method_call(DBusConnection* bus_conn,DBusMessage* bus_msg){
    DBusMessage* reply;
    DBusMessageIter args;
    char* param = nullptr;
    dbus_uint32_t level = 21614;
    dbus_uint32_t serial = 0;

    //读取参数
    if (!dbus_message_iter_init(bus_msg, &args)){
        cout<<"dbus method call :Message has no arguments"<<endl;
        return;
    }
    else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args)){
        cout<<"dbus method call :Argument is not string"<<endl;
        return;
    }else{
        dbus_message_iter_get_basic(&args, &param);
        cout<<"dbus method call get argument : "<<param<<endl;
    }

    //创建返回
    reply = dbus_message_new_method_return(bus_msg);

    //添加返回数据
    dbus_message_iter_init_append(reply, &args);

    if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_UINT32, &level)) {
        cout<<"dbus method call append data:Out Of Memory"<<endl;
        return;
    }

    //发送返回
    if (!dbus_connection_send(bus_conn, reply, &serial)) {
        cout<<"dbus method call send :Out Of Memory"<<endl;
        return;
    }
    dbus_connection_flush(bus_conn);
    dbus_message_unref(reply);
}
上一篇:数据爬取存储到MySQL中


下一篇:Matlab连接MySQL