DBUS
[D-BUS] method 기본 예제 (request/response)
2025. 10. 16. 00:25반응형
dbus-send --session --dest=org.example.CalculatorService --type=method_call \
--print-reply \
/org/example/Calculator \
org.example.Calculator.Sub \
double:5.0 double:2.0
소스코드
파일 : dbus_method_receiver.c
#include <stdio.h>
#include <glib.h>
#include <gio/gio.h>
/* 인터페이스 XML 정의 */
static const gchar *interface_xml =
"<node>"
" <interface name='org.example.Calculator'>"
" <method name='Add'>"
" <arg type='d' name='a' direction='in'/>"
" <arg type='d' name='b' direction='in'/>"
" <arg type='d' name='result' direction='out'/>"
" </method>"
" <method name='Sub'>"
" <arg type='d' name='a' direction='in'/>"
" <arg type='d' name='b' direction='in'/>"
" <arg type='d' name='result' direction='out'/>"
" </method>"
" </interface>"
"</node>";
guint registration_id = 0;
static GDBusNodeInfo *introspection_data = NULL;
/* 메소드 호출 처리 */
static void handle_method_call(GDBusConnection *connection,
const gchar *sender,
const gchar *object_path,
const gchar *interface_name,
const gchar *method_name,
GVariant *parameters,
GDBusMethodInvocation *invocation,
gpointer user_data)
{
// 디버깅 정보 출력
gchar *parameters_str = g_variant_print(parameters, TRUE);
printf("Sender: %s\n", sender);
printf("Object Path: %s\n", object_path);
printf("Interface: %s\n", interface_name);
printf("method_name: %s\n", method_name);
printf("Parameters: %s\n", parameters_str);
g_free(parameters_str);
if (g_strcmp0(interface_name, "org.example.Calculator") == 0)
{
if (g_strcmp0(method_name, "Add") == 0)
{
gdouble a, b;
g_variant_get(parameters, "(dd)", &a, &b);
double result = a + b;
// 결과 반환
g_dbus_method_invocation_return_value(invocation,
g_variant_new("(d)", result));
}
else if (g_strcmp0(method_name, "Sub") == 0)
{
gdouble a, b;
g_variant_get(parameters, "(dd)", &a, &b);
double result = a - b;
// 결과 반환
g_dbus_method_invocation_return_value(invocation,
g_variant_new("(d)", result));
}
}
}
// 버스 이름 획득시 호출
static void on_bus_acquired(GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
GError *error = NULL;
// 인터페이스 vtable 정의. vtable은 D-Bus 인터페이스의 동작을 정의하는 콜백함수 테이블로
// 클라이언트 요청을 처리할 수 있도록 인터페이스의 동작을 구성하는데 사용
GDBusInterfaceVTable interface_vtable = {
handle_method_call, // D-Bus methods(request)를 처리할 때
NULL, /* get_property, */ // D-Bus 속성을 읽을 때
NULL /* set_property */ // D-Bus 속성을 설정할 때
};
// 객체 등록.
// D-Bus method(requeest) 처리를 하기위해 vtable을
// D-Bus 연결에 특정 객체 경로와 인터페이스를 등록하는 함수
// 이 함수가 호출 되어야, 특정 객체 경로로 부터 받은 D-Bus method(reqeust) 요청을 처리할 수 있다.
registration_id = g_dbus_connection_register_object(connection,
"/org/example/Calculator",
introspection_data->interfaces[0],
&interface_vtable,
NULL, /* user_data */
NULL, /* user_data_free_func */
&error);
if (registration_id == 0)
{
g_printerr("Failed to register object: %s\n", error->message);
g_error_free(error);
return 1;
}
}
int main(int argc, char *argv[])
{
GMainLoop *loop;
GDBusConnection *connection;
GError *error = NULL;
guint owner_id;
g_type_init();
loop = g_main_loop_new(NULL, FALSE);
// 인트로스펙션 데이터 생성
introspection_data = g_dbus_node_info_new_for_xml(interface_xml, NULL);
// D-Bus에 서비스 등록
owner_id = g_bus_own_name(G_BUS_TYPE_SESSION,
"org.example.CalculatorService",
G_BUS_NAME_OWNER_FLAGS_NONE,
on_bus_acquired, /* on_bus_acquired */
NULL, /* on_name_acquired */
NULL, /* on_name_lost */
NULL, /* user_data */
NULL); /* user_data_free_func */
// 세션 D-BUS 연결
connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
if (connection == NULL)
{
g_printerr("Failed to connect to D-Bus: %s\n", error->message);
g_error_free(error);
return 1;
}
g_print("Calculator service is running...\n");
// 메인 루프 실행
g_main_loop_run(loop);
// 종료 후 clean-up (리소스 정리)
g_dbus_connection_unregister_object(connection, registration_id);
g_bus_unown_name(owner_id);
g_object_unref(connection);
g_main_loop_unref(loop);
g_dbus_node_info_unref(introspection_data);
return 0;
}
컴파일 방법
gcc -o dbus_method_receiver dbus_method_receiver.c `pkg-config --cflags --libs gio-2.0`
dbus-send 명령어 (Add)
dbus-send --session --dest=org.example.CalculatorService \
--type=method_call \
--print-reply \
/org/example/Calculator \
org.example.Calculator.Add \
double:3.5 double:2.5
실행 결과
method return time=1639623456.789012 sender=:1.123 -> destination=:1.124 serial=456 reply_serial=2
double 6
dbus-send 명령어 (Sub)
dbus-send --session --dest=org.example.CalculatorService \
--type=method_call \
--print-reply \
/org/example/Calculator \
org.example.Calculator.Sub \
double:5.0 double:2.0
실행 결과
method return time=1639623456.789012 sender=:1.123 -> destination=:1.124 serial=457 reply_serial=2
double 3
dbus-send sender 코드
- 파일: dbus_method_sedner.c
#include <glib.h>
#include <gio/gio.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
GDBusConnection *connection;
GError *error = NULL;
GVariant *result;
// GLib 타입 시스템 초기화
g_type_init();
// 세션 버스에 연결
connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
if (connection == NULL) {
g_printerr("Failed to connect to D-Bus: %s\n", error->message);
g_error_free(error);
return 1;
}
// Add 메서드 호출
printf("Calling Add(3.5, 2.5)...\n");
result = g_dbus_connection_call_sync(
connection,
"org.example.CalculatorService", // 서비스 이름
"/org/example/Calculator", // 객체 경로
"org.example.Calculator", // 인터페이스 이름
"Add", // 메서드 이름
g_variant_new("(dd)", 3.5, 2.5), // 입력 인자 (두 개의 double)
G_VARIANT_TYPE("(d)"), // 예상 반환 타입 (double)
G_DBUS_CALL_FLAGS_NONE,
-1, // 타임아웃 (기본값)
NULL, // GCancellable
&error
);
if (result == NULL) {
g_printerr("Error calling Add: %s\n", error->message);
g_error_free(error);
} else {
gdouble add_result;
g_variant_get(result, "(d)", &add_result);
printf("Add result: %f\n", add_result);
g_variant_unref(result);
}
// Sub 메서드 호출
printf("Calling Sub(5.0, 2.0)...\n");
result = g_dbus_connection_call_sync(
connection,
"org.example.CalculatorService",
"/org/example/Calculator",
"org.example.Calculator",
"Sub",
g_variant_new("(dd)", 5.0, 2.0),
G_VARIANT_TYPE("(d)"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error
);
if (result == NULL) {
g_printerr("Error calling Sub: %s\n", error->message);
g_error_free(error);
} else {
gdouble sub_result;
g_variant_get(result, "(d)", &sub_result);
printf("Sub result: %f\n", sub_result);
g_variant_unref(result);
}
// 리소스 정리
g_object_unref(connection);
return 0;
}
dbus-send sender 코드 (비동기)
- 파일: dbus_method_sender_async.c
#include <glib.h>
#include <gio/gio.h>
#include <stdio.h>
// Add 메서드 호출 콜백
static void add_callback(GDBusConnection *connection,
GAsyncResult *res,
gpointer user_data)
{
GError *error = NULL;
GVariant *result = g_dbus_connection_call_finish(connection, res, &error);
if (result == NULL) {
g_printerr("Error calling Add: %s\n", error->message);
g_error_free(error);
} else {
gdouble add_result;
g_variant_get(result, "(d)", &add_result);
printf("Add result: %f\n", add_result);
g_variant_unref(result);
}
// 메인 루프 종료 (첫 번째 호출 완료 후)
g_main_loop_quit((GMainLoop *)user_data);
}
// Sub 메서드 호출 콜백
static void sub_callback(GDBusConnection *connection,
GAsyncResult *res,
gpointer user_data)
{
GError *error = NULL;
GVariant *result = g_dbus_connection_call_finish(connection, res, &error);
if (result == NULL) {
g_printerr("Error calling Sub: %s\n", error->message);
g_error_free(error);
} else {
gdouble sub_result;
g_variant_get(result, "(d)", &sub_result);
printf("Sub result: %f\n", sub_result);
g_variant_unref(result);
}
// 두 번째 호출 완료 후
g_main_loop_quit((GMainLoop *)user_data);
}
int main(int argc, char *argv[])
{
GDBusConnection *connection;
GError *error = NULL;
GMainLoop *loop;
// GLib 타입 시스템 초기화
g_type_init();
// 메인 루프 생성
loop = g_main_loop_new(NULL, FALSE);
// 세션 버스에 연결
connection = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
if (connection == NULL) {
g_printerr("Failed to connect to D-Bus: %s\n", error->message);
g_error_free(error);
return 1;
}
// Add 메서드 비동기 호출
printf("Calling Add(3.5, 2.5) asynchronously...\n");
g_dbus_connection_call(
connection,
"org.example.CalculatorService", // 서비스 이름
"/org/example/Calculator", // 객체 경로
"org.example.Calculator", // 인터페이스 이름
"Add", // 메서드 이름
g_variant_new("(dd)", 3.5, 2.5), // 입력 인자 (두 개의 double)
G_VARIANT_TYPE("(d)"), // 예상 반환 타입 (double)
G_DBUS_CALL_FLAGS_NONE,
-1, // 타임아웃 (기본값)
NULL, // GCancellable
(GAsyncReadyCallback)add_callback, // 콜백 함수
loop // 콜백에 전달할 사용자 데이터
);
// 메인 루프 실행 (Add 호출 완료까지 대기)
g_main_loop_run(loop);
// Sub 메서드 비동기 호출
printf("Calling Sub(5.0, 2.0) asynchronously...\n");
g_dbus_connection_call(
connection,
"org.example.CalculatorService",
"/org/example/Calculator",
"org.example.Calculator",
"Sub",
g_variant_new("(dd)", 5.0, 2.0),
G_VARIANT_TYPE("(d)"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
(GAsyncReadyCallback)sub_callback,
loop
);
// 메인 루프 실행 (Sub 호출 완료까지 대기)
g_main_loop_run(loop);
// 리소스 정리
g_object_unref(connection);
g_main_loop_unref(loop);
return 0;
}
반응형
'DBUS' 카테고리의 다른 글
| [DBUS] Ubuntu에서 glib, gio 라이브러리 설치하기 (glib-2.0, gio-2.0) (0) | 2025.11.25 |
|---|---|
| [DBUS] gdbus-codegen을 활용한 기본 예제 (0) | 2025.11.25 |
| [D-BUS] signal 기본 예제 (0) | 2025.10.15 |
| (임) DBUS 그림 (0) | 2025.10.15 |
| [DBUS] Get/SetProperty 방법 (프로퍼티 설정 방법) (0) | 2025.06.23 |
