한국어
오픈소스포럼
 이곳은 다양한 오픈소스 프로젝트를 소개하고 리뷰, 활용 방법을 공유합니다.

GDBus 튜토리얼(GDBus tutorial)

makersweb 2019.06.30 00:02 조회 수 : 10215

이 글은 간단한 예제를 통해 GDBus사용법을 설명한다.

 

GDBus는 GLib에 포함되어 제공되므로 먼저 관련 개발 패키지를 설치해야한다.

참고로 GLib은 GTK+ 프로젝트의 일부로 시작되었으며 비 GUI 적인 크로스 플랫폼 소프트웨어 유틸리티 세트이다. 플랫폼에 독립적인 응용프로그램을 만들 수 있도록 API를 제공한다.

https://developer.gnome.org/glib/

 

GIO는 다음의 Low-level D-Bus API 및

D-Bus Utilities — Various utilities related to D-Bus

D-Bus Addresses — D-Bus connection endpoints

D-Bus Introspection Data — Node and interface description data structures

GDBusError — Mapping D-Bus errors to and from GError

GDBusMessage — D-Bus Message

GDBusConnection — D-Bus Connections

GDBusMethodInvocation — Object for handling remote calls

GDBusServer — Helper for accepting connections

GDBusAuthObserver — Object used for authenticating connections

 

Highlevel D-Bus API를 제공한다.

Owning Bus Names — Simple API for owning bus names

Watching Bus Names — Simple API for watching bus names

GDBusInterface — Base type for D-Bus interfaces

GDBusInterfaceSkeleton — Service-side D-Bus interface

GDBusProxy — Client-side D-Bus interface proxy

GDBusObject — Base type for D-Bus objects

GDBusObjectSkeleton — Service-side D-Bus object

GDBusObjectProxy — Client-side D-Bus object

GDBusObjectManager — Base type for D-Bus object managers

GDBusObjectManagerServer — Service-side object manager

GDBusObjectManagerClient — Client-side object manager

 

간단한 예제를 통해 익혀보자.

 

운영체제: Linux(Ubuntu18.04)

IDE: QtCreator

 

아래의 명령으로 패키지를 설치할 수 있다.

sudo apt update

sudo apt install libglib2.0-dev

 

다른 DBus 바인딩과 비슷하게 GDBus도 DBus 인터페이스를 설명하는(객체의 인터페이스, 메소드 및 시그널등) XML형식의 문서 즉, DBus Introspection를 작성한다.

 

간단한 Introspection XML 예제.

net.Makersweb.Media.Playback.xml

<node>
  <interface name="net.Makersweb.Media.Playback">
    <method name="Play">
      <arg name="index" direction="in" type="i"/>
    </method>

    <method name="Pause"></method>

    <method name="Prev"></method>

    <method name="Next"></method>

    <signal name="PlaybackStateChanged">
      <arg name="state" type="i"/>
    </signal>

    <property name="CurrentTrack" type="i" access="read"/>
  </interface>
</node>

 

gdbus-codegen 사용

이 Introspection XML은 gdbus-codegen 을 통해서 D-Bus 인터페이스를위한 클라이언트 및 서버 측 래퍼를 생성할 수 있다.

gdbus-codegen --generate-c-code playback-generated    \
              --c-namespace example                   \
              --interface-prefix net.Makersweb.Media. \
              net.Makersweb.Media.Playback.xml

 

위의 명령줄로 playback-generated.c 와 playback-generated.h 파일이 만들어 진다.

 

다음은 gdbus-codegen 옵션에 대한 간단한 설명이다.

--interface-prefix org.project.Prefix.
모든 D-Bus 인터페이스 이름에서 제거하기위한 접두어.
 
--generate-docbook OUTFILES
Generate Docbook Documentation for each D-Bus interface and put it in OUTFILES-NAME.xml where NAME is a place-holder for the interface name, e.g. net.Corp.FooBar and so on.
 
--generate-c-code OUTFILES
모든 D-Bus 인터페이스에 대한 C 코드를 생성하여 OUTFILES.c 및 OUTFILES.h를 만든다.
 
--c-namespace YourProject
생성 된 C 코드에 사용할 네임 스페이스.
 
--c-generate-object-manager
이 옵션이 전달되면 적합한 GDBusObject, GDBusObjectProxy, GDBusObjectSkeleton 및 GDBusObjectManagerClient 하위 클래스를 생성.
 
--annotate ELEMENT KEY VALUE
지정된 XML 파일에 D-Bus 주석을 삽입하는 데 사용.

 

QtCreator사용

IDE는 QtCreator를 사용하며 다음의 프로젝트파일(.pro)처럼 glib관련 라이브러리를 추가해줘야 한다.

xyz.pro

CONFIG += link_pkgconfig
PKGCONFIG += glib-2.0 gio-2.0 gio-unix-2.0

 

서버측 구현(Server Side)

생성된 playback-generated.h파일을 include하여 랩핑 함수들을 사용한다.

#include "playback-generated.h"

 

mediaplayback.cpp

세션 버스에 이름 등록

MediaPlayback::MediaPlayback()
{
    /* Register bus name */
    m_busId = g_bus_own_name (G_BUS_TYPE_SESSION,
                              "net.Makersweb.Examples.Media",
                              (GBusNameOwnerFlags)(G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT | G_BUS_NAME_OWNER_FLAGS_REPLACE),
                              on_bus_acquired,
                              on_name_acquired,
                              nullptr,
                              nullptr,
                              nullptr);
}

 

bus_type에 의해 지정된 버스에서 이름 획득을 시작하고 이름이 획득되면 각각 on_bus_acquired 및 on_name_acquired가 호출된다.

examplePlayback * MediaPlayback::m_obj = nullptr;

void MediaPlayback::on_bus_acquired(GDBusConnection *connection, const gchar *name, gpointer user_data)
{
    g_print ("Acquired a message bus connection\n");

    m_obj = example_playback_skeleton_new();

    example_playback_set_current_track(m_obj, 0);

    /* Handle Play() D-Bus method invocations on the .Playback interface */
    g_signal_connect (m_obj,
                      "handle-play",
                      G_CALLBACK (on_handle_play),
                      nullptr); /* user_data */

    GError *error = nullptr;

    if (!g_dbus_interface_skeleton_export ( G_DBUS_INTERFACE_SKELETON (m_obj),
                                            connection,
                                            "/path/of/dbus_object",
                                            &error))
    {
        /* handle error */
    }
}

 

D-Bus인터페이스 Play()의 콜백함수

gboolean MediaPlayback::on_handle_play(examplePlayback *interface, GDBusMethodInvocation *invocation, gint trackIndex, gpointer user_data)
{
    if(trackIndex >= 0){
        /* Play track Sequence */
        example_playback_set_current_track(m_obj, trackIndex);

        /* D-Bus 메서드 호출 완료 함수 */
        example_playback_complete_play(interface, invocation);
    }
    else {
        g_dbus_method_invocation_return_dbus_error (invocation,
                                                    "Media.Playback.Error.play",
                                                    "invalid track.");
    }

    return TRUE;
}

 

main함수

#include "mediaplayback.h"

gint main (gint argc, gchar *argv[]){
    GMainLoop *loop;
    guint id;

    g_type_init ();

    loop = g_main_loop_new (nullptr, FALSE);

    MediaPlayback * playback = new MediaPlayback;

    g_main_loop_run (loop);

    g_bus_unown_name (id);
    g_main_loop_unref (loop);

    return 0;
}

 

예제: gdbus_server.tar.gz

 

클라이언트측 (Client Side)

 

번호 제목 글쓴이 날짜 조회 수
35 Pluma(C++ Plug-in Management Framework) 튜토리얼 file makersweb 2019.12.07 13944
» GDBus 튜토리얼(GDBus tutorial) file makersweb 2019.06.30 10215
33 Dear ImGui, 경량의 C++ 용 GUI 및 Widget 라이브러리 file makersweb 2020.11.28 8913
32 ZeroMQ의 기본 메세지 패턴들 file makersweb 2020.07.31 8377
31 GENIVI DLT(Diagnostic Log and Trace) 활용 file makersweb 2020.11.19 8069
30 텔레그램(Telegram) Bot 개발 file makersweb 2019.07.21 5681
29 webOS소개 및 Raspberry Pi 3 에서 실행 file makersweb 2019.10.13 3853
28 가볍고 쉬운 임베디드용 그래픽 라이브러리 - LVGL file makersweb 2020.09.16 3226
27 [SDL2 와 OpenGL]윈도우 생성과 2D그래픽 file makersweb 2020.04.11 3026
26 리눅스에서 SDL2 최신버전 컴파일과 Qt Creator로 개발환경 구성 file makersweb 2019.10.06 3010
25 Flutter Application 에서 한글(EUC-KR) 깨져서 나오는 문제 file makersweb 2022.01.06 2585
24 Wayland IVI Extension 간단 리뷰 file makersweb 2019.05.12 2242
23 Nana, C++용 크로스플랫폼 GUI 라이브러리 file makersweb 2021.01.06 2024
22 AGL (Automotive Grade Linux) 개요 file makersweb 2022.06.19 1808
21 ZeroMQ 비동기 클라이언트/서버 패턴 file makersweb 2020.08.13 1725
20 CANdevStudio 를 사용하여 CAN 네트워크 시뮬레이션 file makersweb 2021.03.09 1628
19 Flutter/Dart 와 Qt/QML 비교 file makersweb 2021.11.07 1336
18 Qt와 GStreamer 로 작성한 flac 오디오 재생 예제 file makersweb 2020.09.05 1125
17 LVGL 을 통해 GUI 구현 시 한글 폰트 추가 file makersweb 2023.02.07 998
16 [NodeGui] JavaScript로 데스크탑 응용프로그램 작성 file makersweb 2023.02.21 963