Как я не разделяю внешнюю переменную между экземплярами?
РЕДАКТИРОВАТЬ: это переписать вопрос, так как он был настолько неопределенным раньше.
Поэтому у меня возникла проблема с решением вопроса о том, какие переменные будут совместно использоваться экземплярами в расширениях 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 ответа
Хорошо, теперь я думаю, что вижу проблему. Ваш
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 не будут видны кодом, связывающим общий объект / статическую библиотеку.
Глобальные переменные соответствуют спецификации расширений ruby c, совместно используемых друг с другом (см. Документацию). Это лучший вариант ограничить области видимости до наименее видимых, которые выполняют свою работу. Если у вас есть общая переменная, она должна быть по крайней мере безопасна для проблем синхронизации.