Computer Science Canada

A Challenge

Author:  wtd [ Sat Dec 24, 2005 12:14 am ]
Post subject:  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:

code:
#include <stdio.h>

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.

code:
>> require "foo"
=> true
>> print_foo
foo
=> nil
>>

Author:  wtd [ Sat Dec 24, 2005 12:59 am ]
Post subject: 

A further challenge along the same lines.

Write pure Ruby code which does the same as this Ruby extension written in C.

code:
#include <ruby.h>

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);

}

Author:  rdrake [ Sat Dec 24, 2005 8:00 pm ]
Post subject: 

The first one I can get to work, but not 100% correctly.
code:
#include <stdio.h>
#include <ruby.h>

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
code:
> require 'foo'
=> true
> Foo.new
foo
I think that's close enough.

It looks like the second would be something like the following.
code:
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
Use the following code to test it.
code:
foobar = Foo.new
foobar.bar(41)
I think that's it anyways.

Author:  wtd [ Sat Dec 24, 2005 8:14 pm ]
Post subject: 

Close, but not quite. Smile

Author:  rdrake [ Sat Dec 24, 2005 8:24 pm ]
Post subject: 

How about this for the second?
code:
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.

Author:  wtd [ Sat Dec 24, 2005 8:35 pm ]
Post subject: 

cartoon_shark wrote:
How about this for the second?
code:
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. Smile

code:
#include <stdio.h>
#include <ruby.h>

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);
}

Author:  wtd [ Sat Dec 24, 2005 10:34 pm ]
Post subject: 

http://ruby-doc.org/doxygen/1.8.2/ruby_8h.html

Author:  rdrake [ Sun Dec 25, 2005 9:44 am ]
Post subject: 

No wonder why I turned to Ruby...


: