web-dev-qa-db-ja.com

インタープリターをフリーズせずに、インタープリター内でGUIフレームワークをベイクする方法を教えてください。

単純なプログラミング言語のCでバイトコードインタープリターを書いています。

言語にGUI機能を追加したい。最初のステップとして、GTKライブラリのラッパーをインタープリターに焼き込むことにしました。組み込みモジュールとしてユーザーコードに公開されます。

私の問題は、GTKがスレッドを制御することによって機能することです。C関数g_application_runを呼び出すと、スレッドはGTK内で無限のリスニングループに入ります。

なぜこれが問題なのですか?このGTKループで「スタック」している間、インタープリターのバイトコード解釈ループがフリーズするためです。デモ用の擬似バイトコード:

0 SOME OPCODE
1 SOME OTHER OPCODE
2 OPCODE INVOKING GTK WRAPPER FUNCTION <-- GTK invoked in C level and enters an endless loop
3 MORE OPCODES  <-------- This is never executed

これに対抗するために最初に考えたのは、GTKラッパーを、Cライブラリの使用方法に合わせて「1:1ミラーリングに近い」スタイルで設計することでした。たとえば、擬似コードでは:

import gtk
func app_code() {
    # ... app code ...
}
gtk.application_run(app_code)

これでおそらく問題が解決します。g_application_run内でGTKエンドレスループを終了しないように気を付けてください。自分のユーザーコードを呼び出す責任があるからです。

これが機能しない理由:インタープリター内でユーザー関数を呼び出す方法は、

  1. コールスタックに新しいスタックフレームをプッシュする
  2. 呼び出された関数のバイトコードの先頭を指すように命令ポインターを設定する
  3. バイトコード解釈ループの次の反復で、新しい関数は自然に実行を開始します

GTKラッパーはステップ1と2を簡単に実行できます。ただし、GTK無限ループ内でスタックしているため、ステップ3は決して発生しません。インタープリターループが新しい反復を開始することはありません。

だから私の質問は:この問題を解決するための可能なオプションは何ですか?できれば、この問題が既存のプロジェクトでどのように処理されるかの例は何ですか?

  • 別のCレベルのスレッドでGTKループを開始しますか?
  • GTKを放棄し、「フレームワーク-y」が少なく、「ライブラリ-y」が多いタイプのGUIツールキットを探します。これはスレッド制御を取得しませんか?
  • 他のオプションはありますか?
3
Aviv Cohn

c関数g_application_runを呼び出すと、スレッドはGTK内で無限の待機ループに入ります。

それは起こることのほんの一部です。ここで最初に行う必要があるのは、たとえばg_signal_connectを使用して、イベントのコールバックを登録することです。これにより、GTKがそれらを呼び出します(最初、プログラムの開始時、または後で、マウスボタンを押すなどのユーザーアクションが発生したとき)行事)。これらのコールバックはC関数である必要がありますが、おそらくこれらの呼び出しを独自のインタープリタ言語で記述された関数にマッピングする必要があります。

だからここであなたがしなければならないことは

  • GTKにイベントを登録するために、いくつかのコマンドを言語で実装します。これらのコマンドは、g_signal_connectなどのメソッドへの実際の呼び出しをラップする必要があります。

  • ラッパーは、インタープリターの固定ディスパッチャーメソッドのアドレスを、gtkメソッドへの実際のコールバックとして渡す必要があります。

  • g_signal_connectdataパラメータには、インタプリタの状態への参照を保持するオブジェクトと、プログラミング言語の関数コールバックアドレスに相当するものを含める必要があります。

これで、イベントが発生すると、GTKはそのデータオブジェクトでディスパッチャーメソッドを呼び出し、ディスパッチャーメソッドはそこから「コールバックアドレス」を取り出し、それに応じて命令ポインターを初期化し、インタープリターループを開始します。インタープリターループは、特定のイベントのコードが完全に実行されるたびに終了します。したがって、得られるのは「1つの巨大な無限インタープリターループ」ではなく、いくつかの短期間のインタープリター呼び出しです。

2
Doc Brown