카테고리 없음
[DBUS] gdbus-codegen을 활용한 기본 예제 - 3. 다양한 파라미터
2025. 11. 27. 00:51반응형
이 예제를 통해, 다양한 타입(정수(i), 문자열(s), 불리언(b))로 파라미터를 받아 DBus Method call을 처리하고 다양한 타입으로 반환해본다.
프로젝트 구조
project/
├── CMakeLists.txt
├── example.xml
├── server.cpp
└── client.cpp
example.xml
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.example.Calculator">
<method name="Add">
<arg type="i" name="a" direction="in"/>
<arg type="i" name="b" direction="in"/>
<arg type="i" name="result" direction="out"/>
</method>
<method name="Sub">
<arg type="i" name="a" direction="in"/>
<arg type="i" name="b" direction="in"/>
<arg type="i" name="result" direction="out"/>
</method>
<method name="RegisterName">
<arg type="s" name="inputLastName" direction="in"/>
<arg type="s" name="inputFirstName" direction="in"/>
<arg type="s" name="outputFullName" direction="out"/>
</method>
<method name="Alert">
</method>
<method name="Warning">
<arg type="s" name="inputLastName" direction="in"/>
</method>
<method name="Power">
<arg type="b" name="mode" direction="in"/>
<arg type="b" name="status" direction="out"/>
</method>
<signal name="CalculationDone">
<arg type="s" name="operation"/>
<arg type="i" name="result"/>
</signal>
</interface>
</node>
server.cpp
#include <glib.h>
#include <gio/gio.h>
#include <string>
extern "C" {
#include "calculator-generated.h"
}
static Calculator *calculator_skeleton = nullptr;
static gboolean power_status = FALSE;
extern "C" {
static gboolean
on_handle_add(Calculator *object,
GDBusMethodInvocation *invocation,
gint a, gint b,
gpointer user_data)
{
gint result = a + b;
calculator_complete_add(object, invocation, result);
gchar *msg = g_strdup_printf("Add(%d, %d)", a, b);
calculator_emit_calculation_done(object, msg, result);
g_free(msg);
g_print("Add: %d + %d = %d\n", a, b, result);
return TRUE;
}
static gboolean
on_handle_sub(Calculator *object,
GDBusMethodInvocation *invocation,
gint a, gint b,
gpointer user_data)
{
gint result = a - b;
calculator_complete_sub(object, invocation, result);
gchar *msg = g_strdup_printf("Sub(%d, %d)", a, b);
calculator_emit_calculation_done(object, msg, result);
g_free(msg);
g_print("Sub: %d - %d = %d\n", a, b, result);
return TRUE;
}
static gboolean
on_handle_register_name(Calculator *object,
GDBusMethodInvocation *invocation,
const gchar *last_name,
const gchar *first_name,
gpointer user_data)
{
gchar *full_name = g_strdup_printf("%s %s", first_name, last_name);
calculator_complete_register_name(object, invocation, full_name);
g_print("RegisterName: %s + %s = %s\n", first_name, last_name, full_name);
g_free(full_name);
return TRUE;
}
static gboolean
on_handle_alert(Calculator *object,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
g_print("Alert: No arguments received\n");
calculator_complete_alert(object, invocation);
return TRUE;
}
static gboolean
on_handle_warning(Calculator *object,
GDBusMethodInvocation *invocation,
const gchar *last_name,
gpointer user_data)
{
g_print("Warning: Received last name = %s\n", last_name);
calculator_complete_warning(object, invocation);
return TRUE;
}
static gboolean
on_handle_power(Calculator *object,
GDBusMethodInvocation *invocation,
gboolean mode,
gpointer user_data)
{
power_status = mode;
g_print("Power: Mode set to %s\n", mode ? "ON" : "OFF");
calculator_complete_power(object, invocation, power_status);
return TRUE;
}
static void
on_bus_acquired(GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
GError *error = nullptr;
calculator_skeleton = calculator_skeleton_new();
g_signal_connect(calculator_skeleton, "handle-add",
G_CALLBACK(on_handle_add), nullptr);
g_signal_connect(calculator_skeleton, "handle-sub",
G_CALLBACK(on_handle_sub), nullptr);
g_signal_connect(calculator_skeleton, "handle-register-name",
G_CALLBACK(on_handle_register_name), nullptr);
g_signal_connect(calculator_skeleton, "handle-alert",
G_CALLBACK(on_handle_alert), nullptr);
g_signal_connect(calculator_skeleton, "handle-warning",
G_CALLBACK(on_handle_warning), nullptr);
g_signal_connect(calculator_skeleton, "handle-power",
G_CALLBACK(on_handle_power), nullptr);
if (!g_dbus_interface_skeleton_export(
G_DBUS_INTERFACE_SKELETON(calculator_skeleton),
connection,
"/org/example/Calculator",
&error))
{
g_printerr("Failed to export object: %s\n", error->message);
g_error_free(error);
}
else
{
g_print("Calculator service ready\n");
}
}
static void
on_name_acquired(GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
g_print("Name acquired: %s\n", name);
}
static void
on_name_lost(GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
g_printerr("Name lost: %s\n", name);
}
}
int main(void)
{
GMainLoop *loop;
guint owner_id;
loop = g_main_loop_new(nullptr, FALSE);
owner_id = g_bus_own_name(G_BUS_TYPE_SESSION,
"org.example.Calculator",
G_BUS_NAME_OWNER_FLAGS_NONE,
on_bus_acquired,
on_name_acquired,
on_name_lost,
nullptr, nullptr);
g_main_loop_run(loop);
g_bus_unown_name(owner_id);
g_main_loop_unref(loop);
if (calculator_skeleton)
g_object_unref(calculator_skeleton);
return 0;
}
client.cpp
#include <glib.h>
#include <gio/gio.h>
extern "C" {
#include "calculator-generated.h"
}
extern "C" {
static void
on_calculation_done(Calculator *proxy,
const gchar *operation,
gint result,
gpointer user_data)
{
g_print("Signal received: %s = %d\n", operation, result);
}
}
int main(void)
{
GError *error = nullptr;
Calculator *proxy;
gint result;
gchar *full_name = nullptr;
gboolean power_status;
proxy = calculator_proxy_new_for_bus_sync(
G_BUS_TYPE_SESSION,
G_DBUS_PROXY_FLAGS_NONE,
"org.example.Calculator",
"/org/example/Calculator",
nullptr, &error);
if (error)
{
g_printerr("Failed to create proxy: %s\n", error->message);
g_error_free(error);
return 1;
}
// Signal 연결
g_signal_connect(proxy, "calculation-done",
G_CALLBACK(on_calculation_done), nullptr);
// 1. Add 호출
g_print("\n=== Testing Add ===\n");
if (calculator_call_add_sync(proxy, 10, 5, &result, nullptr, &error))
{
g_print("Add result: %d\n", result);
}
else
{
g_printerr("Add failed: %s\n", error->message);
g_clear_error(&error);
}
// 2. Sub 호출
g_print("\n=== Testing Sub ===\n");
if (calculator_call_sub_sync(proxy, 10, 5, &result, nullptr, &error))
{
g_print("Sub result: %d\n", result);
}
else
{
g_printerr("Sub failed: %s\n", error->message);
g_clear_error(&error);
}
// 3. RegisterName 호출
g_print("\n=== Testing RegisterName ===\n");
if (calculator_call_register_name_sync(proxy, "Kim", "Chulsoo",
&full_name, nullptr, &error))
{
g_print("RegisterName result: %s\n", full_name);
g_free(full_name);
}
else
{
g_printerr("RegisterName failed: %s\n", error->message);
g_clear_error(&error);
}
// 4. Alert 호출 (인자 없음)
g_print("\n=== Testing Alert ===\n");
if (calculator_call_alert_sync(proxy, nullptr, &error))
{
g_print("Alert: Success (no return value)\n");
}
else
{
g_printerr("Alert failed: %s\n", error->message);
g_clear_error(&error);
}
// 5. Warning 호출 (입력만 있고 출력 없음)
g_print("\n=== Testing Warning ===\n");
if (calculator_call_warning_sync(proxy, "Park", nullptr, &error))
{
g_print("Warning: Success (no return value)\n");
}
else
{
g_printerr("Warning failed: %s\n", error->message);
g_clear_error(&error);
}
// 6. Power 호출 (boolean 타입)
g_print("\n=== Testing Power ===\n");
if (calculator_call_power_sync(proxy, TRUE, &power_status, nullptr, &error))
{
g_print("Power result: %s\n", power_status ? "ON" : "OFF");
}
else
{
g_printerr("Power failed: %s\n", error->message);
g_clear_error(&error);
}
// Signal 수신 대기
g_print("\n=== Waiting for signals (Press Ctrl+C to exit) ===\n");
GMainLoop *loop = g_main_loop_new(nullptr, FALSE);
g_main_loop_run(loop);
g_object_unref(proxy);
g_main_loop_unref(loop);
return 0;
}
빌드
mkdir build && cd build
cmake ..
make
실행방법
서버측:
./calculator_server
클라이언트측:
./calculator_client
실행결과
서버측:
Calculator service ready
Name acquired: org.example.Calculator
Add: 10 + 5 = 15
Sub: 10 - 5 = 5
RegisterName: Chulsoo + Kim = Chulsoo Kim
Alert: No arguments received
Warning: Received last name = Park
Power: Mode set to ON
클라이언트측:
=== Testing Add ===
Add result: 15
=== Testing Sub ===
Sub result: 5
=== Testing RegisterName ===
RegisterName result: Chulsoo Kim
=== Testing Alert ===
Alert: Success (no return value)
=== Testing Warning ===
Warning: Success (no return value)
=== Testing Power ===
Power result: ON
=== Waiting for signals (Press Ctrl+C to exit) ===
Signal received: Add(10, 5) = 15
Signal received: Sub(10, 5) = 5
반응형
