Ruby extension (binding)

ผมและพวกเขียน Ruby binding ไว้ที่ http://rubyforge.org/projects/linkgrammar4r/ เขียนด้วย C ทั้งหมดเลย แต่ว่าที่นี้อยากสร้าง layer ขึ้นมาซ้อน แต่อยากเขียนเป็น Ruby ซ้อนไว้อีกที อย่างเช่น ตอนนี้ผมมี

CNode#next
CNode#child

ผมก็อยากจะเขียนอะไรไปซ้อนไว้ให้มันใช้ง่ายๆ แบบ

CNode.each{|node| ... } อะไรแบบนี้ได้ แต่ไม่อยากไปเขียนไว้เป็น ภาษาซีแล้ว ควรจะทำไงดี?

มีท่าเขียน Ruby แยกต่างหาก แล้วแก้ extconf.rb ให้มันลงไปด้วยเปล่า?

class ของ ruby มัน open เสมอนะ
ดังนั้นถ้าเรา define class ไว้ด้วย C
ก็ยังสามารถมา open class นั้นด้วย ruby ได้

ตัวอย่าง

#include "ruby.h"
 
static VALUE
rb_val()
{
  int x = 10;
  return INT2NUM(x);
}
 
void
Init_mytest()
{
  VALUE rb_cls = rb_define_class("Pok", rb_cObject);
  rb_define_method (rb_cls, "val", rb_val, 0);
}

เราสามารถเพิ่ม method เข้าไปใน class Pok ได้

class Pok
  def doubleVal
    val * 2
  end
end

ทดสอบ run

irb(main):003:0> p = Pok.new
=> #<Pok:0xb78d0f9c>
irb(main):004:0> p.doubleVal
=> 20
irb(main):005:0>

สิ่งที่น่าสนใจก็คือลำดับ
อย่างข้างล่างนี้ เราลอง load ruby file ก่อน c file

irb(main):001:0> require 'pok'
=> true
irb(main):002:0> p = Pok.new
=> #<Pok:0xb78f4b90>
irb(main):003:0> p.doubleVal
NameError: undefined local variable or method `val' for #<Pok:0xb78f4b90>
	from ./pok.rb:3:in `doubleVal'
	from (irb):3
irb(main):004:0> require 'mytest'
=> true
irb(main):005:0> p.doubleVal
=> 20
irb(main):006:0> 
veer's picture

ขอบคุณมากครับ ตอนนี้ท่าที่นึกได้คือ rename cmodule ไปอีกชื่อ เช่นเป็น clinkgrammar.c แล้วค่อย สร้าง linkgrammar.rb มาให้ load clinkgrammar.so อีกที แล้วก็ไปแก้ๆ class

เดี่ยวลองดูดีหว่า :-)

ย้าย Codenone

ประกาศย้าย Codenone ไปใช้ Forum ของ Blognone แทนครับ ตามไปตั้งกระทู้ต่อได้ที่ Codenone Forum (รายละเอียดอ่านจากกระทู้ ย้าย Codenone ไปรวมกับ Blognone)

กระทู้เก่าๆ จะย้ายตามไปในภายหลัง ตอนนี้ปิดการโพสต์กระทู้ไว้ เหลือไว้เฉพาะอ้างอิงเท่านั้น