Now let's have a look at how rocaml works. I'm gonna translate an example in rubyinline to rocaml. Since rubyinline supports basic type transaltion between Ruby and C, the orginal example is forced to declare a lot of complex data type defined in ruby.h by hand:
require 'rubygems' require 'inline' class Check class << self inline do |builder| builder.c_raw " static VALUE check(int argc, VALUE *argv, VALUE self) { double x = NUM2DBL(RARRAY(argv[1])->ptr[0]); double y = NUM2DBL(RARRAY(argv[1])->ptr[1]); int len = RARRAY(argv[0])->len; double last_x = NUM2DBL(RARRAY(RARRAY(argv[0])->ptr[len-1])->ptr[0]); double last_y = NUM2DBL(RARRAY(RARRAY(argv[0])->ptr[len-1])->ptr[1]); double cur_x, cur_y = 0.0; int i, c = 0; for (i = 0; i < len; i++) { cur_x = NUM2DBL(RARRAY(RARRAY(argv[0])->ptr[i])->ptr[0]); cur_y = NUM2DBL(RARRAY(RARRAY(argv[0])->ptr[i])->ptr[1]); if ((((cur_y <= y) && (y < last_y)) || ((last_y <= y) && (y < cur_y))) && (x < (last_x - cur_x) * (y - cur_y) / (last_y - cur_y) + cur_x)) { c = !c; } last_x = cur_x; last_y = cur_y; } if (c == 1) return Qtrue; return Qfalse; } " end end end
comparing to Ocaml code:
let check polygon point = let len = Array.length polygon in let last = polygon.(len - 1) in let result = ref false in for i = 0 to (len - 1) do let current = polygon.(i) in if ((current.(1) <= point.(1) && last.(1) > point.(1)) || (last.(1) <= point.(1) && current.(1) > point.(1))) && (point.(0) < ((last.(0) -. current.(0)) *. (point.(1) -. current.(1)) /. (last.(1) -. current.(1)) +. current.(0))) then begin result := not !result end; last.(0) <- current.(0); last.(1) <- current.(1) done; !result open Callback let _ = register "Check.check" check
and then we only have to declare a simple function interface in extconf.rb:
Interface.generate("check") do def_module("Check") do fun "check", [ARRAY(ARRAY(FLOAT)), ARRAY(FLOAT)] => BOOL end end
Unfortunately though the ocaml code is more clear than the C one without being polluted by all kinds of type constants, the benchmark shows the rocaml extension is about 5 times slower than the C one. It seems the type conversion is still pricy considering Ocaml code generally should be on the same page with C in terms of speed.