Как я не разделяю внешнюю переменную между экземплярами? - PullRequest
0 голосов
/ 26 июня 2011

РЕДАКТИРОВАТЬ: это переписать вопрос, поскольку раньше он был настолько неопределенным.

Так что у меня возникла проблема с решением проблемы распределения переменных между экземплярами в расширениях 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)

ИлиЕсть ли в С решение, которое я не вижу или не понимаю?

Код:

#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 ]

1 голос
/ 26 июня 2011

Хорошо, теперь я думаю, что вижу проблему.Ваше

  VALUE test_var;

является своего рода «общим» значением для каждого экземпляра тестового класса.Конечно, это ошибка, поскольку она перезаписывается при создании новых экземпляров или при вызове набора методов.Таким образом, вы можете иметь только один экземпляр и значение, совместно используемое для каждого экземпляра.

Конечно, вы делаете что-то не так: ruby ​​должен предоставить контекст и способ его получения, скорее всего, протокол для функции get должениметь как минимум VALUE self в качестве аргумента, например, set.Значение не может быть сохранено в глобальной или статической локальной переменной: оно должно быть каким-то образом сохранено в «контексте» объекта.Чтобы узнать, как это сделать, мне нужно быстрое руководство по 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?), И искренне не знаю.

«Глобальная» переменная, объявленная как статическая, является локальной для файла, в котором она определена, и не может быть доступна извне, т.е. она является глобальной в этом файле, но она не является глобальной для всех связанных файлов.

func1 может получить доступ к панели, действительно;это не может быть сделано только потому, что символ неизвестен до тех пор, пока он не объявлен (по той же причине, что func1 не может вызвать func2, или, по крайней мере, компилятор выдаст предупреждение об отсутствующем прототипе, тогда код func2 будет найден в любом случае),но в любом случае, когда символ известен, к нему можно получить доступ.Напротив, эти переменные bar и foo не видны извне (и поэтому не являются глобальными), поскольку символы foo и bar не видны.

Если этот код предполагается скомпилировать как общийобъект или статическая библиотека, foo и bar не будут видны кодом, связывающим общий объект / статическую библиотеку.

1 голос
/ 26 июня 2011

Глобальные переменные соответствуют спецификации расширений ruby ​​c, совместно используемых друг с другом (см. документация ).Это лучший вариант ограничить области видимости до наименее видимых, которые выполняют свою работу.Если у вас есть общая переменная, она должна быть по крайней мере безопасна для проблем синхронизации.

...