2017-08-25 13 views
3

DBusの応答にコールバック関数を使用しようとすると、うまく機能しているメインループの作成に取り掛かることになります。低レベルのDBus C APIのメインループ

私がやりたいことは単純ですが、DBus呼び出しを行い、応答が来たときに呼び出される関数を指定します。これは、回答が計算されて到着するまで、スレッド全体をブロックしたくないからです。

まずdbus_connection_send_with_reply(..)を使用してDBusPendingCallを取得した後、dbus_pending_call_set_notify(..)を使用してコールバック関数を指定します。これを行う前に、バスに接続するとき、私は応答を待ってコールバック関数を呼び出すべき別のスレッドを開始しました。私は例を全く見つけず、このようにdbusメインループをどのように設計すべきかについての非常に良い文書はありません。私が試してみました:私はMY_DBUS_STATUS_STOPPINGにdbus->ステータスフラグを設定し、スレッドが参加するのを待つことにより、アプリケーションを停止しよう

  • // Main dbus loop handling data transfer and callbacks.. 
    void *dbus_main(void *args) 
    { 
        my_dbus dbus = (my_dbus)args; 
    
        while (MY_DBUS_STATUS_STOPPING != dbus->status 
          && dbus_connection_read_write_dispatch(dbus->conn, -1)) 
         ; 
    
        return 0; 
    } 
    
    // Start the dbus main loop in a new thread 
    void dbus_main_start(my_dbus dbus) { 
        if (!pthread_create(&dbus->th, NULL, dbus_main, dbus)) { 
         // PRINT ERROR 
        } 
    } 
    

    私の問題は二つのことです。スレッドがdbus_connection_read_write_dispatch(..)関数でブロックされている場合、これは機能しません。私はアプリを速く停止したい場合、私は非常に短いタイムアウトを指定する必要があります。ブロックされたスレッドを別の方法で起きさせることはできませんか?

  • さらに深刻なことに、このコードでは、私が呼び出すメソッドからコールバックを取得しません。 stdoutに書き込むためにfprintf(..)を追加すると、私は突然コールバックを取得する可能性があります。それは非常にランダムなので、デッドロックのいくつかの種類のようですか?私は、dbus_connection_flush(..)の間にメッセージを送信し、_set_notify(..)関数でコールバックを追加することを試みました。違いはありません...しかし、同じ場所でstdoutにいくつかの文字を印刷すると、問題が修正されます。 dbus-main-loop instedの空の ";"のstdoutへの出力すなわち_block(..)を使用していない、非同期メソッドと一緒に低レベルのdbusのAPIを使用する例があり、誰だから... ...時々

をトリックを行うようだ??

答えて

0

それは、非常にはのlibdbusは、あなたが見つけているように、正しく使用するために手間のかかるあるとしてあなたは、D-バスライブラリのlibdbus以外を使用することをお勧めです。可能であれば、より使いやすいより高いレベルのバインディングであるため、代わりにGDBusまたはQtDBusを使用してください。下位レベルのバインディングが必要な場合は、sd-busがlibdbusよりも現代的です。

GDBusを使用する場合は、GMainLoopを使用してメインループを実装できます。 sd-busを使用する場合は、sd-eventを使用できます。セットアップするには

0

次のようにあなたは、単純なDバスのアプリケーションを作成することができます...

、着信メッセージを処理するサーバー、メッセージを処理するための関数ポインタを含む仮想テーブルにdbus_connection_register_object_path通過を呼び出します。以下のような:

{ .unregister_function = UnregisteredMessage, .message_function = ServiceMessage }

応答を処理するコールバック関数を関連付けることdbus_connection_send_with_replyを呼び出してから、dbus_pending_call_set_notify、新しいメッセージを送信します。

次は、DBusにサービスを提供する必要があります。以下に示すように、これは、別のスレッドで、同じスレッドで非ブロッキング呼び出しを定期的に呼び出すことによって行うことができます。

/* Non-blocking read of the next available message */ 
dbus_connection_read_write (MyDBusConnection, 0) ; 

while (dbus_connection_get_dispatch_status (MyDBusConnection) == DBUS_DISPATCH_DATA_REMAINS) 
{ 
    dbus_connection_dispatch (MyDBusConnection) ; 
} 

ここDBUS CのAPIを使用していくつかの良い例があります:http://www.matthew.ath.cx/misc/dbus

関連する問題