
-----------------------------------
wtd
Sat Dec 24, 2005 12:14 am

A Challenge
-----------------------------------
Beyond the usual TYS questions, I have a challenge for those who consider themselves good Ruby programmers.

I have the following C function:

#include 

void print_foo()
{
   puts("foo");
}

Make it possible to call this function from Ruby.  Do not modify the "print_foo" C function itself, though you may add more code to the "foo.c" source file.

>> require "foo"
=> true
>> print_foo
foo
=> nil
>>

-----------------------------------
wtd
Sat Dec 24, 2005 12:59 am


-----------------------------------
A further challenge along the same lines.

Write pure Ruby code which does the same as this Ruby extension written in C.

#include 

static VALUE cFoo;

static VALUE foo_initialize(VALUE self)
{
   rb_iv_set(self, "@bar", rb_int_new(42));
}

static VALUE foo_set_bar(VALUE self, VALUE new_val)
{
   int old_bar = FIX2INT(rb_iv_get(self, "@bar"));
   int new_bar = FIX2INT(new_val);

   if (new_bar > old_bar)
   {
      rb_iv_set(self, "@bar", new_val);
   }
}


void Init_foo()

{
   cFoo = rb_define_class("Foo", rb_cObject);
   rb_define_method(cFoo, "initialize", foo_initialize, 0);
   rb_define_attr(cFoo, "bar", 1, 0);
   rb_define_method(cFoo, "bar=", foo_set_bar, 1);

}

-----------------------------------
rdrake
Sat Dec 24, 2005 8:00 pm


-----------------------------------
The first one I can get to work, but not 100% correctly.#include 
#include  

static VALUE foo_class;

void print_foo() 
{ 
   puts("foo"); 
}

static VALUE foo_initialize(VALUE self)
{
   print_foo();
}

void Init_foo()
{
   foo_class = rb_define_class("Foo", rb_cObject);
   rb_define_method(foo_class, "initialize", foo_initialize, 0);
   rb_define_attr(foo_class, "bar", 1, 0);
   rb_define_method(foo_class, "bar", foo_initialize, 0);
}Here's how you use it> require 'foo'
=> true
> Foo.new
fooI think that's close enough.

It looks like the second would be something like the following.class Foo
  def initialize
    @bar = 42
  end
  
  def bar(new_val)
    old_bar = @bar
    new_bar = new_val
    
    if new_bar > old_bar then
      @bar = new_val
    end
  end
endUse the following code to test it.foobar = Foo.new
foobar.bar(41)I think that's it anyways.

-----------------------------------
wtd
Sat Dec 24, 2005 8:14 pm


-----------------------------------
Close, but not quite.  :)

-----------------------------------
rdrake
Sat Dec 24, 2005 8:24 pm


-----------------------------------
How about this for the second?class Foo
  def initialize
    @bar = 42
  end
  
  def bar=(new_val)
    old_bar = @bar
    new_bar = new_val
    
    if new_bar > old_bar then
      @bar = new_val
    end
  end
end

Foo.new.bar=(41)My solution to the first is posted above.

-----------------------------------
wtd
Sat Dec 24, 2005 8:35 pm


-----------------------------------
How about this for the second?class Foo
  def initialize
    @bar = 42
  end
  
  def bar=(new_val)
    old_bar = @bar
    new_bar = new_val
    
    if new_bar > old_bar then
      @bar = new_val
    end
  end
end

Foo.new.bar=(41)My solution to the first is posted above.

Very good.

Your answer to the first one is too complicated.  :)

#include 
#include 

void print_foo()
{
   puts("foo");
}

static VALUE wrapped_print_foo(VALUE self)
{
   print_foo();
   return Qnil;
}

void Init_foo()
{
   rb_define_method(rb_cObject, "print_foo", wrapped_print_foo, 0);
}

-----------------------------------
wtd
Sat Dec 24, 2005 10:34 pm


-----------------------------------
http://ruby-doc.org/doxygen/1.8.2/ruby_8h.html

-----------------------------------
rdrake
Sun Dec 25, 2005 9:44 am


-----------------------------------
No wonder why I turned to Ruby...
