如何跨实例共享外部变量?

时间:2011-06-26 17:56:26

标签: c ruby ruby-c-extension

编辑:这是对问题的重写,因为之前它是如此不明确。

所以我在解决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);
}

2 个答案:

答案 0 :(得分:1)

全局变量是根据彼此共享的ruby c扩展的规范(参见documentation)。这是将变量范围限制为最少可见范围的最佳选择。如果碰巧有共享变量,那么同步问题应该至少是安全的。

答案 1 :(得分:1)

好的,现在我觉得我看到了问题。你的

  VALUE test_var;

是测试类的每个实例之间的一种“共享”值。当然这是一个错误,因为它会在创建新实例或调用方法集时被覆盖。因此,您只需要在每个实例之间共享一个实例和值。

当然你做错了什么:ruby必须提供上下文和检索它的方法,get函数的proto可能必须至少有VALUE self作为参数,比如set。该值不能存储到全局或静态局部变量中:它必须存储在对象的“上下文”中。为了知道如何操作,我需要一个关于ruby ext的快速教程。在此期间,请尝试深入阅读here

特别要注意“访问变量”以及如何定义实例变量。

我做到了这一点,似乎有效;你可以通过它来实现你的扩展目的(我已经重命名了一些东西,并修复了其他东西;我还删除了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确实可以访问吧台;它不能仅仅因为符号在声明之前是未知的(出于同样的原因,func1不能调用func2,或者至少编译器会给缺少的原型发出警告,那么无论如何都会找到func2的代码),但无论如何,一旦知道了符号,就可以访问它。相反,那些变量bar和foo不能从外部看到(因此不是全局的)因为符号foo和bar不可见。

如果应该将此代码编译为共享对象或静态库,则链接共享对象/静态库的代码将无法看到foo和bar。