Fredrik Jagenheim wrote: > ts wrote: > > > > Well, in ruby > > [snip solution in ruby] > > I had to interface with a C-library that took, among other things, an > array of bitmaps as input. Otherwise, I would have done it in Ruby, of > course. > I assumed it was mainly for experimentation until you said that. Your example showed the first mutable Fixnum object that I've seen and you must have wondered why a simple task was so tough to get right in an extension. Have a look at the same thing implemented (for amusement only) as an extension to the Integer class (Fixnum/Bignum's parent). Notice how the input array is created from a sequence of parameters in both the Ruby and C versions, so you call with (1,2,3) instead of ([1,2,3]). (Method Bitmask#add_bits is defined with "-1" arguments.) Method Bitmask#add_bit in Ruby is now: bitmask | 1 << bit not: bitmask |= 1 << bit which means that you would need bitmask = bitmask.add_bit(...) when accumulating single results. Apart from this "new" problem, you should find that things look simpler (e.g. no Bitmask.new). > As for the solution, Tim was correct in that rb_iterate wasn't what I > neded. The for loop solved the problem I had. OK, I saw that, but you may be tempted to try another approach. A similar loop to Tim's is still there. It's a kind of "Hello bit-World" extension if anyone needs one :-) > > Thanks everyone, > //Fredrik > and thank you, :daz -------8<------ Bitmask.c #include "ruby.h" static ID id_lshift, id_or; static VALUE add_bit(VALUE obj, VALUE bit) /* OK with Fixnum or Bignum */ { VALUE bit_or = rb_funcall(INT2FIX(1), id_lshift, 1, bit); return rb_funcall(obj, id_or, 1, bit_or); } static VALUE bm_add_bit(VALUE self, VALUE bit) { return add_bit(self, bit); } static VALUE bm_add_bits(int argc, VALUE *argv, VALUE self) { VALUE arr_bits, result = self; int x; rb_scan_args(argc, argv, "0*", &arr_bits); for (x = 0; x < RARRAY(arr_bits)->len; x++) result = add_bit(result, RARRAY(arr_bits)->ptr[x]); return result; } void Init_Bitmask() { rb_define_method(rb_cInteger, "add_bit", bm_add_bit, 1); rb_define_method(rb_cInteger, "add_bits", bm_add_bits, -1); id_lshift = rb_intern("<<"); id_or = rb_intern("|"); } /* E N D */ /*** ###----- extconf.rb require 'mkmf' create_makefile('Bitmask') # - to build ... # make # - then ... # make install ###----- test_Bitmask.rb require 'Bitmask' class Integer def add_rubits(*args) ### Ruby add_bits res = self args.each {|bx| res = res.add_bit(bx)} res end end show = lambda{ |res| puts 'value: 0x%03x [%08b]' % [res, res] } bm = 0 show[ bm = bm.add_bit(2) ] show[ bm = bm.add_bit(4) ] puts '------------' show[ 0.add_bits(2, 4) ] puts '------------' MSK1 = 0b11110011 bm = MSK1; show[ bm.add_bits( 31, 33) ] bm = MSK1; show[ bm.add_rubits(31, 33) ] # Ruby bit_arr = [31, 33] bm = MSK1; show[ bm.add_bits(*bit_arr) ] puts '------------' MSK2 = 2**41 bm = MSK2; show[ bm.add_bits( 19, 3, 9, 17, 6, 18) ] bm = MSK2; show[ bm.add_rubits(19, 3, 9, 17, 6, 18) ] # Ruby ***/