認為 VALUE 在 function 傳遞參數時大量使用是 YARV 程式不易理解的原因之一。
例如 load_file_internal
:
static VALUE
load_file_internal(VALUE argp_v)
{
struct load_file_arg *argp = (struct load_file_arg *)argp_v;
//...
argp_v
應該要在 function declaration 明確定義型別就好,這裡卻宣告成 VALUE
再 type cast。function return type 也是,看完程式可以知道回傳的是 rb_ast_t*
但也是宣告成 VALUE
然後 return 時多 type cast。
推想這樣實作的原因,看能否幫助理解。看呼叫 load_file_internal
的程式,只有一個地方:
static rb_ast_t *
load_file(VALUE parser, VALUE fname, VALUE f, int script, ruby_cmdline_options_t *opt)
{
struct load_file_arg arg;
arg.parser = parser;
arg.fname = fname;
arg.script = script;
arg.opt = opt;
arg.f = f;
return (rb_ast_t *)rb_ensure(load_file_internal, (VALUE)&arg,
restore_load_file, (VALUE)&arg);
}
在呼叫時並不是直接呼叫,而是將 function pointer 透過 rb_ensure
呼叫,在交給 rb_ensure
時將要傳入的參數都轉型成 VALUE
。應該是因為這個需求所以設計了 VALUE
這樣中介的型別。另一個問題是那為什麼不是用 void*
呢?猜測是因為類似 rb_ensure
這樣的 API 除了在 YARV 內部的實作使用之外,可能 ruby 程式經過 parse/compile 之後也會呼叫到,那個場景下傳的參數就會是 Ruby object,有可能出現 FIXNUM
這種不是 pointer 的 object。為了一致性所以傳 VALUE
再於 function 內 cast type。
由此衍生出來的觀察是 YARV 內的 C function 是自己的邏輯與 ruby 程式都會使用到,所以 interface 上使用 VALUE
的設計。這個作法好壞目前還無法判斷。