3

Rubyで拡張できるアプリケーションがあります。スクリプトはアプリケーション自体で作成でき、編集するたびに再ロードされます。したがって、ユーザーがクラスにメソッドを追加すると、すぐに有効になります。ユーザーがメソッドを削除した場合、そのファイルは存在しなくなるため、変更したファイルを実行することはできません。唯一のオプションは、インタプリタの状態をクリアして、すべてのスクリプトを再度リロードすることです。しかし、Rubyは再起動から自分自身を保護します:( eval.c

void ruby_init(void)
{
    int state = ruby_setup();
    if (state) {
        error_print();
        exit(EXIT_FAILURE);
    }
}

int ruby_setup(void)
{
    static int initialized = 0;
    int state;

    if (initialized)
        return 0;
    initialized = 1;

    /* ... */

    return state;
}

ruby_init()また、複数回呼び出すと、スタックの位置に問題が発生し、rubyが追跡してGCを壊す可能性があると思います。アプリケーション全体を再起動することは、GUIインターフェイスを備えているためオプションではありません。また、アプリケーションに新しいGUI要素を挿入するためのQtインターフェースが公開されているため、すべてのルビーのものを別々のプロセスに保持するのは面倒です。もう1つのオプションは、定義されたすべてのメソッド、クラス、定数などを追跡し、コードを再実行する前にそれらの定義を解除することです。簡単な方法はありますか?

4

1 に答える 1

2

はいあります!(私は思う)(これには、他のRubyコードをロードするためにいくつかのRubyコードを使用する必要があります):

$current_env = nil

def reload(code)
  $current_env = Module.new
  $current_env.module_eval(code)
end

はい、それはとても簡単です。プラグインから物事にアクセスする必要があるときはいつでも、モジュールとして$current_envにアクセスするだけです。

$current_env::ExtensionClass.extension_thing

が呼び出されたときに置き換えられる古いクラスのものはreload、次にGCが回避されたときに割り当てが解除されることに加えて、アクセスできなくなります。

于 2013-02-18T16:38:44.600 に答える