待更新: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, ¶m)) {
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, ¶m);
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);
}