简介
D-Bus是一种高级的进程间通信机制,它由freedesktop.org项目提供,使用GPL许可证发行。D-Bus最主要的用途是在Linux桌面环境为进程提供通信,同时能将Linux桌面环境和Linux内核事件作为消息传递到进程。D-Bus的主要概念为总线,注册后的进程可通过总线接收或传递消息,进程也可注册后等待内核事件响应,例如等待网络状态的转变或者计算机发出关机指令。D-Bus已被大多数Linux发行版所采用,开发者可使用D-Bus实现各种复杂的进程间通信任务。
注意,dbus是一个协议,任何人只要按照这个协议就可以和其他符合协议的程序进行通信。官方实现是 libdbus,包含 dbus-monitor等调试命令程序;也还有其他版本的实现,比如systemd库的sd-bus,新版本glib库的GDBus libdbus库直接使用很晦涩难懂,所以有多基于libdbus的封装,称为 dbus binding,比如qt的QtDBus。
有些dbus实现就直接从头到尾自己实现协议,并提供api封装,和libdbus没有关系,比如目前引入的dbus-cxx库
参考资料
环境配置
例程
例程来自官方文档例程,在此我只是把注解都添加了上去,并且添加了多个method。
dbus_cxx_server.cpp
#include <dbus-cxx.h>
#include <unistd.h>
/*
We will define a function that will be our workhorse on the server side.
This function will be the actual function that will be called when the dbus add method is invoked,
so we will name our function similarly.
But, note that the actual name of the function in our program and the name in our dbus server do not have to match.
*/
double add( double param1, double param2 ) { return param1 + param2; }
double sub( double param1, double param2 ) { return param1 - param2; }
double mul( double param1, double param2 ) { return param1 * param2; }
double divv( double param1, double param2 ) { return param1 / param2; }
int main()
{
//Now, we will create a dispatcher(调度) to handle incoming and outgoing messages.
//Handling incoming and outgoing messages can be messy and the Dispatcher class handles much of this for us.
std::shared_ptr<DBus::Dispatcher> dispatcher = DBus::StandaloneDispatcher::create(); //standalone表示独立
//Now that we have a dispatcher we need to create a connection to the session bus.
std::shared_ptr<DBus::Connection> conn = dispatcher->create_connection(DBus::BusType::SESSION);
//Next, we need to request a name that will identify our application on the session bus.
if( conn->request_name( "dbuscxx.quickstart_0.server", DBUSCXX_NAME_FLAG_REPLACE_EXISTING ) != DBus::RequestNameResponse::PrimaryOwner )
return 1;
//Now that our application has a name on the bus we need to add an object with it's path.
std::shared_ptr<DBus::Object> object = conn->create_object("/dbuscxx/quickstart_0", DBus::ThreadForCalling::DispatcherThread);
//We will now create a method named add for our object.
//The functionality of the method will be provided by the function we declared above also named add().
//We must add this to an interface,
//and the D-Bus specification required that interface names must contain at least one . (period) character so we will use the interface name "dbuscxx.Quickstart".
object->create_method<double(double,double)>("dbuscxx.Quickstart", "add", sigc::ptr_fun(add));
object->create_method<double(double,double)>("dbuscxx.Quickstart", "sub", sigc::ptr_fun(sub));
object->create_method<double(double,double)>("dbuscxx.Quickstart", "mul", sigc::ptr_fun(mul));
object->create_method<double(double,double)>("dbuscxx.Quickstart", "divv", sigc::ptr_fun(divv)); //这个名字是div的话会出现重载问题
/*
sigc::ptr_fun(T_return(* func)(T_args...))
Creates a functor of type sigc::pointer_functor which wraps an existing non-member function.
*/
sleep(10000);
return 0;
}
dbus_cxx_client.cpp
#include <dbus-cxx.h>
#include <iostream>
int main()
{
//Create a dispatcher to manage threads, timeouts and I/O watches
std::shared_ptr<DBus::Dispatcher> dispatcher;
dispatcher = DBus::StandaloneDispatcher::create();
//Create a connection to the D-Bus session bus
std::shared_ptr<DBus::Connection> connection;
connection = dispatcher->create_connection( DBus::BusType::SESSION );
//create an object proxy, which stands in for a real object.(stand in:替身)
//a proxy exists over the dbus
std::shared_ptr<DBus::ObjectProxy> object;
object = connection->create_object_proxy("dbuscxx.quickstart_0.server", "/dbuscxx/quickstart_0");
//a method proxy acts like a real method, but will go over the dbus
//to do its work.
DBus::MethodProxy<double(double,double)>& add_proxy
= *(object->create_method<double(double,double)>("dbuscxx.Quickstart","add"));
DBus::MethodProxy<double(double,double)>& sub_proxy
= *(object->create_method<double(double,double)>("dbuscxx.Quickstart","sub"));
DBus::MethodProxy<double(double,double)>& mul_proxy
= *(object->create_method<double(double,double)>("dbuscxx.Quickstart","mul"));
DBus::MethodProxy<double(double,double)>& div_proxy
= *(object->create_method<double(double,double)>("dbuscxx.Quickstart","divv"));
double answer;
answer = add_proxy( 1.1, 2.2 );
std::cout << "1.1 + 2.2 = " << answer << std::endl;
answer = sub_proxy( 1.1, 2.2 );
std::cout << "1.1 - 2.2 = " << answer << std::endl;
answer = mul_proxy( 12300.1, 36.2 );
std::cout << "12300.1 * 36.2 = " << answer << std::endl;
answer = div_proxy( 9.1, 3.2 );
std::cout << "9.1 / 3.2 = " << answer << std::endl;
return 0;
}
Makefile
.PHONY:clean
LD_LIBRARY_PATH:= /home/minshilzm/dbux-cxx/dbus-cxx-2.3.0/build:/home/minshilzm/libsigc++-3.0.0/__install/lib
CXXFLAG = -std=c++17 -O3
PKGFLAG = `pkg-config --cflags --libs dbus-cxx-2.0`
SERVER_SRC = dbus_cxx_server.cpp
CLIENT_SRC = dbus_cxx_client.cpp
SERVER_TARGET = dbus_cxx_server
CLIENT_TARGET = dbus_cxx_client
all: $(SERVER_TARGET) $(CLIENT_TARGET)
$(SERVER_TARGET):$(SERVER_SRC)
g++ $(CXXFLAG) $(SERVER_SRC) -o $(SERVER_TARGET) $(PKGFLAG)
$(CLIENT_TARGET):$(CLIENT_SRC)
g++ $(CXXFLAG) $(CLIENT_SRC) -o $(CLIENT_TARGET) $(PKGFLAG)
clean:
rm $(SERVER_TARGET) $(CLIENT_TARGET)
make完之后要在环境变量配置动态库路径,我用的是bash,所以有:
(1)vi ~/.bashrc
(2)添加
export LD_LIBRARY_PATH=/home/minshilzm/dbux-cxx/dbus-cxx-2.3.0/build:/home/minshilzm/libsigc+±3.0.0/__install/lib:$LD_LIBRARY_PATH
export PKG_CONFIG_PATH=/home/minshilzm/libsigc+±3.0.0/__install/lib/pkgconfig:$PKG_CONFIG_PATH
运行结果
最后这个div咋回事还在找原因…