7

I am looking for a function which can get me all the keys from hash or I can loop through the hash to retrieve single key at a time.

Currently I am hardcoding key

VALUE option = rb_hash_aref(options, rb_str_new2("some_key"));
Uri Agassi
  • 36,848
  • 14
  • 76
  • 93
mandss
  • 91
  • 6

2 Answers2

2

You can iterate over the key/value pairs with a callback function using rb_hash_foreach (blog post w/an example):

void rb_hash_foreach(VALUE, int (*)(ANYARGS), VALUE);

There is an rb_hash_keys in MRI, but it's not in any header files it seems, so using it may be risky.

Nick Veys
  • 23,458
  • 4
  • 47
  • 64
  • Yup `rb_hash_keys` complains `use of undeclared identifier 'rb_hash_keys'` – mandss Dec 10 '14 at 17:58
  • Do you have any working example? I am getting this error `candidate function not viable: no known conversion from 'int (VALUE, VALUE, VALUE)' to 'int (*)(...)' for 2nd argument void rb_hash_foreach(VALUE, int (*)(ANYARGS), VALUE);` – mandss Dec 15 '14 at 19:03
  • The MRI source has an example in `rb_hash_keys`: http://rxr.whitequark.org/mri/source/hash.c#1627 – Nick Veys Dec 15 '14 at 19:06
  • error: use of undeclared identifier 'rb_hash_keys'; – mandss Dec 15 '14 at 20:06
  • Well yeah, that function contains the example. – Nick Veys Dec 15 '14 at 20:07
  • I followed MRI source example but eventually I got the same error `candidate function not viable: no known conversion from 'int (VALUE, VALUE, VALUE)' to 'int (*)(...)' for 2nd argument void rb_hash_foreach(VALUE, int (*)(ANYARGS), VALUE);`This is the code I am trying ` VALUE ary; ary = rb_ary_new(); rb_hash_foreach(opts, convert_keys_to_a, ary);` `static int convert_keys_to_a(VALUE key, VALUE value, VALUE ary) { if (logic) return ST_CONTINUE; if (logic { rb_hash_foreach(value, convert_keys_to_a, ary); } return rb_ary_push(ary, key); }` – mandss Dec 16 '14 at 14:21
  • 1
    What ruby version? Compiler? Compiler flags? How are you building this? Empty functions with these names compiles fine for me using [these basic instructions](http://www.rubyinside.com/how-to-create-a-ruby-extension-in-c-in-under-5-minutes-100.html). – Nick Veys Dec 16 '14 at 15:57
  • If you are compiling for Rubinius, you may need to include the hash libraries yourself (they are not automatically included with ruby.h): `// Force inclusion of hash declarations (only MRI includes by default) #ifdef HAVE_RUBY_ST_H #include "ruby/st.h" #else #include "st.h" #endif` – Neil Slater Jan 12 '15 at 11:54
1

You could always make a call to the Ruby method itself:

VALUE keys = rb_funcall(hash, rb_intern("keys"), 0)
thomthom
  • 2,854
  • 1
  • 23
  • 53