📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)
| (同じ利用者による、間の16版が非表示) | |||
| 42行目: | 42行目: | ||
sdbus-c++ライブラリはsd-busライブラリを使用しているが、必ずしもSystemdに制約されているわけではなく、Systemd以外の環境でも完璧に使用することができる。<br> | sdbus-c++ライブラリはsd-busライブラリを使用しているが、必ずしもSystemdに制約されているわけではなく、Systemd以外の環境でも完璧に使用することができる。<br> | ||
<br> | <br> | ||
sdbus-c++ライブラリの詳細な使用方法を知りたい場合は、[https://kistler-group.github.io/sdbus-cpp/docs/using-sdbus-c++.html sdbus-c++ライブラリの公式Webサイト]を参照すること。<br> | |||
<br> | |||
==== sdbus-c++ライブラリのライセンス ==== | ==== sdbus-c++ライブラリのライセンス ==== | ||
sdbus-c++ライブラリは、LGPL 2.1でライセンスされている。<br> | sdbus-c++ライブラリは、LGPL 2.1でライセンスされている。<br> | ||
ただし、ライブラリのヘッダファイルではLGPL Exception version 1.0ライセンスもあり、これは、以下に示すようなことを許可している。<br> | |||
<br> | <br> | ||
LGPL 2.1に対する追加的な許可として、「ライブラリを使用する作品」のオブジェクトコード形式は、ライブラリの一部であるヘッダファイルの素材を組み込んでもよい。 | LGPL 2.1に対する追加的な許可として、「ライブラリを使用する作品」のオブジェクトコード形式は、ライブラリの一部であるヘッダファイルの素材を組み込んでもよい。 | ||
| 65行目: | 68行目: | ||
==== sdbus-c++ライブラリのインストール ==== | ==== sdbus-c++ライブラリのインストール ==== | ||
===== パッケージ管理システムからインストール ===== | ===== パッケージ管理システムからインストール ===== | ||
# RHEL (EPELリポジトリが必要) | |||
sudo dnf install sdbus-cpp-devel | |||
# SUSE | # SUSE | ||
sudo zypper install sdbus-cpp-devel | sudo zypper install sdbus-cpp-devel | ||
| 70行目: | 76行目: | ||
===== ソースコードからインストール ===== | ===== ソースコードからインストール ===== | ||
sdbus-c++ライブラリのビルドに必要なライブラリをインストールする。<br> | sdbus-c++ライブラリのビルドに必要なライブラリをインストールする。<br> | ||
# RHEL | |||
sudo dnf install pkg-config make cmake gcc gcc-c++ libcap-devel expat-devel systemd-devel | |||
doxygen # ドキュメントもビルドする場合 | |||
# SUSE | # SUSE | ||
sudo zypper install pkg-config make cmake gcc gcc-c++ libcap-devel libexpat-devel systemd-devel | sudo zypper install pkg-config make cmake gcc gcc-c++ libcap-devel libexpat-devel libmount-devel systemd-devel | ||
doxygen # ドキュメントもビルドする場合 | doxygen # ドキュメントもビルドする場合 | ||
<br> | <br> | ||
| 84行目: | 94行目: | ||
<br> | <br> | ||
sdbus-c++ライブラリをビルドおよびインストールする。<br> | sdbus-c++ライブラリをビルドおよびインストールする。<br> | ||
cmake -DCMAKE_INSTALL_PREFIX=<sdbus-c++ライブラリのインストールディレクトリ> \ | cmake -DCMAKE_C_COMPILER=<GCC 8以降のGCCコンパイラのパス> \ | ||
-DCMAKE_BUILD_TYPE=Release | -DCMAKE_CXX_COMPILER=<G++ 8以降のG++コンパイラのパス> \ | ||
-DSDBUSCPP_BUILD_CODEGEN=ON | -DCMAKE_INSTALL_PREFIX=<sdbus-c++ライブラリのインストールディレクトリ> \ | ||
-DSDBUSCPP_BUILD_DOCS=ON | -DCMAKE_BUILD_TYPE=Release \ | ||
- | -DSDBUSCPP_BUILD_CODEGEN=ON \ | ||
-DSDBUSCPP_BUILD_EXAMPLES=ON \ | |||
-DSDBUSCPP_BUILD_DOCS=ON \ | |||
-DSDBUSCPP_BUILD_DOXYGEN_DOCS=ON \ # Doxygenでドキュメントを生成する場合 | |||
.. | .. | ||
| 99行目: | 112行目: | ||
D-Bus経由でSystemdと直接通信するため、より柔軟で、プログラム内から制御できるようになっている。<br> | D-Bus経由でSystemdと直接通信するため、より柔軟で、プログラム内から制御できるようになっている。<br> | ||
<br> | <br> | ||
ただし、サンプルコードを実行するには、適切な権限が必要となる。<br> | |||
<syntaxhighlight lang="c++"> | <syntaxhighlight lang="c++"> | ||
#include <iostream> | |||
#include <string> | |||
#include <sdbus-c++/sdbus-c++.h> | #include <sdbus-c++/sdbus-c++.h> | ||
int main() | // Systemdサービスはシグナルを送信しないため、今回は使用しない | ||
// #include <atomic> | |||
// #include <chrono> | |||
// #include <thread> | |||
// std::atomic<bool> g_keep_running(false); | |||
// UnitStateChangedシグナルハンドラ | |||
// ただし、Systemdサービスはシグナルを送信しないため、今回は定義しない | |||
// void onUnitStateChanged(sdbus::Signal signal) | |||
// { | |||
// std::string unitName, newState, oldState; | |||
// signal >> unitName >> newState >> oldState; | |||
// std::cout << "Unit " << unitName << " changed state from " << oldState << " to " << newState << std::endl; | |||
// if (unitName == "smb.service" && (newState == "active" || newState == "failed")) { | |||
// g_keep_running.store(true); | |||
// } | |||
// } | |||
// smb.serviceが正常に開始されているかどうかを確認する | |||
bool checkServiceStatus(sdbus::IProxy &systemdProxy, sdbus::InterfaceName &interfaceName, const std::string &serviceName) | |||
{ | |||
try { | |||
// smb.serviceのユニットパスを取得する | |||
sdbus::MethodName methodName{"GetUnit"}; | |||
auto method = systemdProxy.createMethodCall(interfaceName, methodName); | |||
method << serviceName; | |||
auto reply = systemdProxy.callMethod(method); | |||
sdbus::ObjectPath unitPath; | |||
reply >> unitPath; | |||
// 取得したsmb.serviceのユニットパスを使用して、smb.serviceの開始状態を取得 | |||
/// D-Busサービス名は、"org.freedesktop.systemd1" | |||
/// D-Busオブジェクト名は、smb.serviceのユニットパス | |||
auto unitProxy = sdbus::createProxy(systemdProxy.getConnection(), std::move(sdbus::ServiceName{"org.freedesktop.systemd1"}), unitPath); | |||
/// D-Busインターフェース名は、"org.freedesktop.DBus.Properties" | |||
/// D-Busインターフェースメソッド名は、"Get" | |||
auto getProperty = unitProxy->createMethodCall(sdbus::InterfaceName{"org.freedesktop.DBus.Properties"}, sdbus::MethodName{"Get"}); | |||
/// D-Busインターフェースメソッド"Get"の引数を指定 | |||
getProperty << "org.freedesktop.systemd1.Unit" << "ActiveState"; | |||
/// D-Busインターフェースメソッドを実行して、戻り値を取得 | |||
auto propertyReply = unitProxy->callMethod(getProperty); | |||
/// 戻り値は文字列型であるため、文字列型に変換 | |||
/// smb.serviceが正常に開始されている場合は、文字列は"active"となる | |||
sdbus::Variant variant; | |||
propertyReply >> variant; | |||
std::string state = variant.get<std::string>(); | |||
return (state == "active"); | |||
} | |||
catch (const sdbus::Error &e) { | |||
// sdbus::Errorをキャッチしてエラーメッセージを表示 | |||
std::cerr << "Error checking service status: " << e.getName() << " - " << e.getMessage() << std::endl; | |||
return false; | |||
} | |||
catch (const std::exception &e) { | |||
// std::exceptionをキャッチして一般エラーを処理 | |||
std::cerr << "Error: " << e.what() << std::endl; | |||
return false; | |||
} | |||
} | |||
int main(int argc, char *argv[]) | |||
{ | { | ||
// システムバスへの接続を作成 | |||
auto connection = sdbus::createSystemBusConnection(); | |||
// Systemdサービスのマネージャーインターフェースへのプロキシオブジェクトを作成 | |||
sdbus::ServiceName destination("org.freedesktop.systemd1"); | |||
sdbus::ObjectPath objectPath("/org/freedesktop/systemd1"); | |||
auto systemdProxy = sdbus::createProxy(*connection, std::move(destination), std::move(objectPath)); | |||
// D-Busインターフェース名を指定 | |||
sdbus::InterfaceName interfaceName("org.freedesktop.systemd1.Manager"); | |||
// UnitStateChangedシグナルのハンドラを登録 | |||
// ただし、Systemdサービスはシグナルを送信しないため、今回は設定しない | |||
//sdbus::SignalName signalName("UnitStateChanged"); | |||
//systemdProxy->registerSignalHandler(interfaceName, signalName, &onUnitStateChanged); | |||
try { | try { | ||
// "StartUnit"はSystemdサービスのメソッド名 | |||
sdbus::MethodName methodName{"StartUnit"}; | |||
auto method = systemdProxy->createMethodCall(interfaceName, methodName); | |||
// Systemdサービスはシグナルを送信しないため、今回は定義しない | |||
//systemdProxy->uponSignal("JobRemoved") | |||
// .onInterface("org.freedesktop.systemd1.Manager") | |||
// .call(&onUnitStateChanged); | |||
// D-Busサービスを実行する | |||
// "smb.service"は開始するSystemdサービス名 | |||
// "replace"はSystemdサービスの起動モード | |||
method << "smb.service" << "replace"; | |||
auto reply = systemdProxy->callMethod(method); | |||
// または、以下に示す方法でもD-Busサービスを実行することができる | |||
//systemdProxy->callMethod("StartUnit") | |||
// .onInterface("org.freedesktop.systemd1.Manager") | |||
// .withArguments("smb.service", "replace"); | |||
// Systmedサービスでsmb.service (D-Busサービス) を開始する場合は、ジョブ番号の値が返る | |||
sdbus::ObjectPath jobPath; | |||
reply >> jobPath; | |||
std::cout << "StartUnit job path: " << jobPath << std::endl; | |||
// イベントループを開始 | |||
// Systemdサービスはシグナルを送信しないため、今回は使用しない | |||
//while (g_keep_running) { | |||
// connection->processPendingEvent(); | |||
// std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 100[mS]のスリープ | |||
// // これにより、CPUの過剰な使用を避けつつ適度な応答性を維持 | |||
//} | |||
// smb.service (D-Busサービス) が正常に開始されたかどうかを確認する | |||
std::string serviceName = "smb.service"; | |||
if (checkServiceStatus(*systemdProxy, interfaceName, serviceName)) { | |||
std::cout << "Service " << serviceName << " state: " << "avtive" << std::endl; | |||
} | |||
} | } | ||
catch (const sdbus::Error &e) { | catch (const sdbus::Error &e) { | ||
// sdbus::Errorをキャッチしてエラーメッセージを表示 | // sdbus::Errorをキャッチしてエラーメッセージを表示 | ||
std::cerr << " | std::cerr << "Error starting smb.service: " << e.getName() << " - " << e.getMessage() << std::endl; | ||
return -1; | return -1; | ||
} | } | ||
| 142行目: | 259行目: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<br> | <br> | ||
<code>processPendingEvent</code>メソッドの意味を以下に示す。<br> | |||
* イベント処理 | |||
*: D-Busシステムから到着した保留中のイベントを1つ処理する。 | |||
*: これには、受信したシグナルやメソッド呼び出しの応答などが含まれる。 | |||
* ノンブロッキング動作 | |||
*: processPendingEventメソッドは、通常、ノンブロッキングで動作する。 | |||
*: つまり、処理すべきイベントがない場合、即座に制御を返す。 | |||
* シングルイベント処理 | |||
*: 1回の呼び出しで1つのイベントのみを処理する。 | |||
*: 複数のイベントを処理するには、このメソッドを繰り返し呼び出す必要がある。 | |||
<br> | |||
==== 使用例 : ユーザ定義のD-Busサービスの実行 ==== | ==== 使用例 : ユーザ定義のD-Busサービスの実行 ==== | ||
===== D-Busサービス ===== | ===== D-Busサービス ===== | ||
| 186行目: | 315行目: | ||
<u>sdbus-c++ライブラリは効率的な引数の受け渡しを行うよう設計されているため、大きなオブジェクトは自動的に参照として扱われる。</u><br> | <u>sdbus-c++ライブラリは効率的な引数の受け渡しを行うよう設計されているため、大きなオブジェクトは自動的に参照として扱われる。</u><br> | ||
<br> | <br> | ||
===== sdbus-c++-xml2cppツール (スタブジェネレータ) の実行 ===== | |||
<u>次に、上記のDBusインターフェース定義ファイルからC++ヘッダファイルを自動生成する。</u><br> | |||
<br> | |||
sdbus-c++ライブラリには、XMLファイルからC++のソースコードを生成するツールであるsdbus-c++-xml2cppツール (スタブジェネレータ) が存在する。<br> | |||
このツールは、D-Busインタフェースを記述したXMLファイルを受け取り、そのインタフェースを経由して呼び出すことができるC++ヘッダファイルを自動生成するものである。<br> | |||
この自動生成されたC++ヘッダファイルは、D-Bus経由の呼び出しをサービスのプロバイダに転送して、結果を呼び出し元に返す役割がある。<br> | |||
<br> | |||
サービスを実装するサーバは、<code>--adaptor</code>オプションで生成されたヘッダファイルのインターフェイスクラスから派生したクラスを定義して、そのメソッドを実装する必要がある。<br> | |||
<br> | |||
以下のコマンド例は、sdbus-c++-xml2cppツールを実行して、D-Busのサーバ側 (ヘルパー実行ファイル) のC++ヘッダファイルを自動生成している。<br> | |||
sdbus-c++-xml2cpp <D-Busインターフェース定義ファイル名 (XMLファイル)> \ | |||
--adaptor=<生成するアダプタのヘッダファイル名> | |||
# 例 : | |||
sdbus-c++-xml2cpp org.example.mochiu.xml \ | |||
--adaptor=MochiuAdaptor.h | |||
<br> | |||
===== D-Busのサーバ側 (ヘルパー実行ファイル) ===== | ===== D-Busのサーバ側 (ヘルパー実行ファイル) ===== | ||
<u> | <u>次に、D-Busのサーバ側 (ヘルパー実行ファイル) を作成する。</u><br> | ||
<br> | |||
<u>上記で自動生成されたC++ヘッダファイルを、ヘルパー実行ファイルのソースコードにインクルードする。</u> | |||
<syntaxhighlight lang="c++"> | |||
// 例: MochiuHelper.hファイル | |||
#include "MochiuAdapter.h" // 生成されたアダプタヘッダをインクルード | |||
</syntaxhighlight> | |||
<br> | |||
<syntaxhighlight lang="c++"> | <syntaxhighlight lang="c++"> | ||
// 例: MochiuHelper.hファイル | // 例: MochiuHelper.hファイル | ||
| 214行目: | 369行目: | ||
} | } | ||
}; | }; | ||
</syntaxhighlight> | |||
#endif // MOCHIUHELPER_H </syntaxhighlight> | |||
<br> | <br> | ||
<syntaxhighlight lang="c++"> | <syntaxhighlight lang="c++"> | ||
| 245行目: | 401行目: | ||
try { | try { | ||
// システムバスを接続する場合 | // システムバスを接続する場合 | ||
auto connection = sdbus:: | auto connection = sdbus::createSystemBusConnection(); | ||
// セッションバスを接続する場合 | // セッションバスを接続する場合 | ||
| 270行目: | 426行目: | ||
return 0; | return 0; | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<br> | <br> | ||
| 311行目: | 446行目: | ||
// 指定されたD-Busサービスとオブジェクトのプロキシオブジェクトを作成 | // 指定されたD-Busサービスとオブジェクトのプロキシオブジェクトを作成 | ||
auto proxy = sdbus::createProxy(*connection, | auto proxy = sdbus::createProxy(*connection, | ||
"org.example.mochiu", // D-Busサービス名 | sdbus::ServiceName{"org.example.mochiu"}, // D-Busサービス名 | ||
"/org/example/mochiu" | sdbus::ObjectPath{"/org/example/mochiu"} // D-Busオブジェクト名 | ||
); | ); | ||
| 320行目: | 455行目: | ||
// D-Busインターフェースメソッド (func1) を呼び出して、戻り値を受け取る | // D-Busインターフェースメソッド (func1) を呼び出して、戻り値を受け取る | ||
auto result = proxy->callMethod("func1") | auto result = proxy->callMethod(sdbus::MethodName{"func1"}) // D-Busインターフェースメソッド名 | ||
.onInterface("org.example.mochiu.method") // D-Busインターフェース名 | .onInterface(sdbus::InterfaceName{"org.example.mochiu.method"}) // D-Busインターフェース名 | ||
.withArguments(arg1, arg2) | .withArguments(arg1, arg2) // 引数を指定 | ||
.returnValue<int>(); | .returnValue<int>(); // 戻り値の型を指定 | ||
std::cout << "Method 'func1' called successfully." << std::endl; | std::cout << "Method 'func1' called successfully." << std::endl; | ||
| 363行目: | 498行目: | ||
<br><br> | <br><br> | ||
{{#seo: | |||
|title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki | |||
|keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板 | |||
|description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux | |||
|image=/resources/assets/MochiuLogo_Single_Blue.png | |||
}} | |||
__FORCETOC__ | __FORCETOC__ | ||
[[カテゴリ:C++]] | [[カテゴリ:C++]] | ||