zoukankan      html  css  js  c++  java
  • C++ d-bus 使用实例

    因为以后工作用的到D-bus,这两天抽空看了下c++下得d-bus的使用方法。因为网上对c++下得d-bus使用说明几乎没有,所以,在这里记录下以供同仁使用。同时感谢shengpeng得demo。

                  这篇文章主要还是对libdbus-c++.so得api调用,其实如果之前有过android下得开发经验,使用过binder得话,对d-bus得工作原理和上手速度会有很大帮助。

                   不多废话,下面进入正题:

                   d-bus得整个架构可以在官方说明文档中看到,如果之前有了解过binder的话,理解起来就会比较轻松。如下:

                      如同binder一样,linux下得IPC需要通过kernel空间得d-bus驱动来进行通信,所以,在进行d-bus通信之前,需要先对安装d-bus得库支持,这里不再详细说明。可以使用系统自带的工具进行安装,例如apt-get install dbus种种。

                      d-bus分为adaptor端和proxy端(和binder是不是很像?),需要在adaptor端和proxy端都创建了各自的实例后,才能进行通信。

                     例如,我在proxy端得进程中创建了一个XXproxy得实例,我就能通过这个实例去调用adaptor端对应实例得相应函数,类似于:XXproxy.getversion()(getversion()是在adaptor端的adaptor类型得方法),如果adaptor端得实例想调用proxy端实例得函数,需要将这个希望调用得函数在XML文件声明为signal类型。

                     上面有说道XML文件,很多人都会疑惑这个XML在d-bus中算作什么角色,其实它相当于一个输入文件,使用d-bus得工具,可以使这个XML自动生成两个类,分别为proxy端和adaptor端的类,程序员再通过继承这两个类,实现这两个类中得纯虚函数,就是完成了proxy端和adaptor端得类的实现。

    下面贴出,我这里使用得XML文件,test.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <node name="/com/test">
    <interface name="com.test.interfacetest">
    <method name="getversion">
    <arg type="s" name="version" direction="out"/>
    </method>

    <signal name="display"/>

    </interface>
    </node>
                       由上面看到,我们定义了一个node,这个node得name表示得是一个地址,这个地址得意义相当于是一个唯一ID,使用得话,记住它是唯一就行了。

                       之后声明了一个方法,方法名为getversion,下面定义了参数得类型。

                       接下来声明了一个signal,上面说过了,这个signal是在adaptor端使用的,后面得代码就可以看到。

                        我们有了XML文件以后,可以通过工具自动生成两个.h文件,一个是proxy端的.h,一个是adaptor端得.h。

                        输入如下命令:

    dbusxx-xml2cpp test.xml --proxy=test_Proxy.h --adaptor=test_adaptor.h
                       后面得参数分别表示输入得xml文件,这里是test.xml,proxy端的.h文件名,这里是test_Proxy.h,adaptor端得.h得文件名,这里是test_adaptor.h。

                       接下来,我们分别来看看这两个.h文件得内容。

    test_Proxy.h
    /*
    * This file was automatically generated by dbusxx-xml2cpp; DO NOT EDIT!
    */

    #ifndef __dbusxx__ANI_proxy_h__PROXY_MARSHAL_H
    #define __dbusxx__ANI_proxy_h__PROXY_MARSHAL_H

    #include <dbus-c++/dbus.h>
    #include <cassert>

    namespace com {
    namespace test {

    class test_proxy
    : public ::DBus::InterfaceProxy
    {
    public:

    test_proxy()
    : ::DBus::InterfaceProxy("com.test.interfacetest")
    {
    connect_signal(test_proxy,display, _display_stub);
    }

    public:

    /* properties exported by this interface */
    public:

    /* methods exported by this interface,
    * this functions will invoke the corresponding methods on the remote objects
    */
    std::string getversion()
    {
    ::DBus::CallMessage call;
    call.member("getversion");
    ::DBus::Message ret = invoke_method (call);
    ::DBus::MessageIter ri = ret.reader();

    std::string argout;
    ri >> argout;
    return argout;
    }


    public:

    /* signal handlers for this interface
    */
    virtual void display() = 0;    //Note:这里是纯虚函数,需要在子类中实现,继承于test_proxy类的子类实现得这个函数则会在proxy端被调用。

    private:

    /* unmarshalers (to unpack the DBus message before calling the actual signal handler)
    */
    void _display_stub(const ::DBus::SignalMessage &sig)
    {
    display();
    }
    };

    } } }
    #endif //__dbusxx__ANI_proxy_h__PROXY_MARSHAL_H
                
                       另一个.h文件也是类似得,都会有纯虚函数,在这个sample里面,是getversion()这个函数,则在adaptor端实现后,就会被proxy端得对应实例调用。

                       从上面得内容可以看到,其实我们有了XML文件以后,要做得工作就是完成其虚函数得实现。子类得具体代码我这里就不贴出来了,基本得C++语法就能解决。

                       实现虚函数以后,我们要做得就是将这些类实例化在进程中调用。

                       我这里得两个main.cpp如下:

    proxy端:
    #include "test_proxy_fill.h"
    #include <signal.h>



    void *runDispatcher(void *v);
    void niam(int sig)
    {
    dispatcher.leave();
    }

    int main(int argc, char *argv[])
    {
    signal(SIGTERM, niam);
    signal(SIGINT, niam);
    DBus::default_dispatcher = &dispatcher;
    DBus::_init_threading();
        DBus::Connection bus = DBus::Connection::SessionBus();

        test_proxy_fill test_proxy(bus, "/com/test", "com.test.test_interface");//test_proxy_fill是test_proxy得继承
     std::string version = test_proxy.getversion(); //这边就相当于是进入到了adaptor端得进程内执行代码
       dispatcher.enter();
        return 1;
    }
    adaptor端:
    #include "test_adaptor_fill.h"

    int main(int argc, char *argv[])
    {
    DBus::_init_threading();
    DBus::default_dispatcher = &dispatcher;
    DBus::Connection bus = DBus::Connection::SessionBus();

    // bus.request_name("com.test.testinterface");

    test_adaptor_fill test_adaptor(bus,"/com/test","com.test.test_interface");//test_adaptor_fill是test_adaptor得继承

    dispatcher.enter();

    return 0;
    }

  • 相关阅读:
    城市联动
    Js-右键事件
    JS-键盘移动事件
    Js-点名器
    前端学习——HTML
    前端学习——前端基础
    Redis数据库学习
    2020系统综合实践 期末大作业
    #Nginx+Tomcat+Redis session共享
    2020系统综合实践 第7次实践作业
  • 原文地址:https://www.cnblogs.com/fire909090/p/14693537.html
Copyright © 2011-2022 走看看