0

編集:以前は非常に具体的ではなかったため、これは質問の書き直しです。

そのため、C 拡張機能のインスタンス間で共有される変数の問題を解決するのに問題があります。これが私が遭遇しているものの例です。

>> t = SCOPE::TestClass.new #=> #<SCOPE::TestClass:0x000001011e86e0>
>> t.set = 4 #=> 4
>> t.get #=> 4
>> v = SCOPE::TestClass.new #=> #<SCOPE::TestClass:0x00000101412bf0>
>> v.set = 5 #=> 5
>> v.get #=> 5
>> t.get #=> 5

以下のコードでの最善の解決策は、次のように設定できる ruby​​ 変数を単純に使用することでしょうか。

void rb_define_variable(const char *name, VALUE *var)

それとも、私が見ていない、または理解していない C の解決策はありますか?

コード:

#include <stdlib.h>
#include <ruby.h>

VALUE TestClass;
VALUE SCOPE;
VALUE test_var;

VALUE set(self, val);
VALUE get();

VALUE set(VALUE self, VALUE val) {
    test_var = NUM2INT(val);
    return Qnil;
}

VALUE get() {
    return INT2NUM(test_var);
}

void Init_scope() 
{
    SCOPE = rb_define_module("SCOPE");
    TestClass = rb_define_class_under(SCOPE, "TestClass", rb_cObject);

    rb_define_method(TestClass, "set=", set, 1);
    rb_define_method(TestClass, "get", get, 0);
}
4

2 に答える 2

1

グローバル変数は、相互に共有される ruby​​ c 拡張機能の仕様に従っています (ドキュメントを参照)。変数のスコープを、ジョブを実行する最も目立たないものに制限するのが最善のオプションです。たまたま共有変数がある場合、少なくとも同期の問題に対して安全である必要があります。

于 2011-06-26T18:10:43.253 に答える
1

わかりました、今私は問題を見たと思います。君の

  VALUE test_var;

テストクラスのすべてのインスタンス間で一種の「共有」値です。新しいインスタンスが作成されるか、メソッドセットが呼び出されると上書きされるため、これはもちろんエラーです。したがって、単一のインスタンスと、すべてのインスタンス間で共有される値を持つことができます。

もちろん、あなたは何か間違ったことをしています: ruby​​ はコンテキストとそれを取得する方法を提供しなければなりません. おそらく get 関数の proto は set のように少なくとも VALUE 個の self を引数として持たなければなりません. 値をグローバル変数または静的ローカル変数に格納することはできません。何らかの方法でオブジェクトの「コンテキスト」に格納する必要があります。その方法を知るために、ruby ext に関する簡単なチュートリアルが必要です。それまでの間、こちらを深く読んでみてください。

特に、「変数へのアクセス」とインスタンス変数の定義方法に注意してください。

私はこれを行いましたが、うまくいくようです。拡張機能の目的を達成するためにそれに取り組みたいと思うかもしれません (私は何かの名前を変更し、何かを修正しました; INT2NUM と NUM2INT のものも削除しました。必要に応じて元に戻すことができます)

#include <stdlib.h>
#include <ruby.h>

VALUE TestClass;
VALUE SCOPE;

VALUE set(VALUE, VALUE);
VALUE get(VALUE);

VALUE set(VALUE self, VALUE val) {
    (void)rb_iv_set(self, "@val", val);
    return Qnil;
}

VALUE get(VALUE self) {
  return rb_iv_get(self, "@val");
}

void Init_RubyTest() 
{
    SCOPE = rb_define_module("RubyTest");
    TestClass = rb_define_class_under(SCOPE, "TestClass", rb_cObject);

    rb_define_method(TestClass, "set=", set, 1);
    rb_define_method(TestClass, "get", get, 0);
}

この質問は、「C 拡張機能」(Ruby に対するものだと思いますか?) がどのように機能するかを知らなければ、完全に答えることはできません。

static として宣言された「グローバル」変数は、それが定義されているファイルに対してローカルであり、外部からアクセスすることはできません。つまり、そのファイル内ではグローバルですが、リンクされたすべてのファイルに対してグローバルではありません。

実際、func1 は bar にアクセスできます。シンボルが宣言されるまでシンボルがわからないという理由だけではできません (同じ理由で、func1 は func2 を呼び出せません。または、少なくともコンパイラーが欠落しているプロトタイプについて警告を出すと、とにかく func2 へのコードが見つかります)、とにかく、シンボルがわかればアクセスできます。逆に、これらの変数 bar と foo は、シンボル foo と bar が表示されないため、外部から見ることができません (つまり、グローバルではありません)。

このコードが共有オブジェクトまたは静的ライブラリとしてコンパイルされることになっている場合、foo と bar は、共有オブジェクト/静的ライブラリをリンクするコードからは見えません。

于 2011-06-26T18:21:54.967 に答える