From: nobu.nokada@... Date: 2003-11-28T14:06:23+09:00 Subject: Re: rb_hash_aref question: symbols vs strings Hi, At Fri, 28 Nov 2003 11:32:08 +0900, Daniel Berger wrote: > If the key "bar" is a string, that works fine. However, that returns > nil (not a symbol) if "bar" is a symbol. I know I can do rb_iterate > and I can detect if hash keys are symbols, but I don't know how to > permanately change the key back to a string, i.e. it appears to pass a > copy of the hash, rather than a reference. Do you use Hash#each_pair or similar? They just ignore returned values from yielded blocks. > // Iterate over hash. Assume that rb_sym2str() works properly. No such function. Instead, you can use rb_to_id() vice versa. ===File foo.c=============================================== #include enum { Foo_test_bar, Foo_test_baz, Foo_test_MAX }; typedef VALUE Foo_test_options[Foo_test_MAX]; static ID id_Foo_test[Foo_test_MAX]; static VALUE parse_hash(VALUE array, Foo_test_options opt) { ID key = rb_to_id(RARRAY(array)->ptr[0]); VALUE val = RARRAY(array)->ptr[1]; int i; for (i = 0; i < Foo_test_MAX; ++i) { if (key == id_Foo_test[i]) { opt[i] = val; return Qnil; } } rb_raise(rb_eArgError, "unknown option - %s", rb_id2name(key)); return Qnil; /* not reached */ } static VALUE foo_s_test(VALUE self, VALUE args) { Foo_test_options opt; VALUE a[3]; int i; Check_Type(args, T_HASH); for (i = 0; i < Foo_test_MAX; ++i) { opt[i] = Qundef; } rb_iterate(rb_each, args, parse_hash, (VALUE)opt); a[0] = rb_str_new2("%p=%p\n"); for (i = 0; i < Foo_test_MAX; ++i) { if (opt[i] != Qundef) { a[1] = ID2SYM(id_Foo_test[i]); a[2] = opt[i]; rb_io_printf(3, a, rb_stdout); } } return self; } void Init_foo(void) { VALUE foo = rb_define_class("Foo", rb_cObject); rb_define_singleton_method(foo, "test", foo_s_test, 1); id_Foo_test[Foo_test_bar] = rb_intern("bar"); id_Foo_test[Foo_test_baz] = rb_intern("baz"); } ============================================================ You can use struct instead of array. -- Nobu Nakada