如何从C扩展名将关键字传递给Ruby方法?

时间:2016-10-29 02:43:57

标签: ruby ruby-c-extension keyword-argument

我正在使用Ruby的C扩展,我想调用一个需要关键字参数的方法,如下所示:

class Word 
  def initialize(line:, col:, value:)
  end 
end 

在C中,我熟悉,通过rb_funcallrb_funcallv调用Ruby方法,但我无法弄清楚如何传递关键字参数!

以下是我尝试过的一些事情:

将哈希作为最后一个位置参数传递给rb_funcall

VALUE kwargs = rb_hash_new();
rb_hash_aset(kwargs, rb_intern("name"), rb_str_new2(name));
// ... 
rb_funcall(Word_Class, rb_intern("new"), 1, kwargs);
// result: ArgumentError: wrong number of arguments (given 1, expected 0)

将其作为argv数组的最后一个成员rb_funcallv传递:

// initialize `kwargs` as above
VALUE argv = rb_ary_new();
rb_ary_push(argv, kwargs);
rb_funcallv(Word_Class, rb_intern("new"), 1, &argv);
// result: ArgumentError: wrong number of arguments (given 1, expected 0)

0传递为argc,即使argv的长度为1

// initialize `argv` as above
rb_funcallv(Word_Class, rb_intern("new"), 0, &argv);
// ArgumentError: missing keywords: line, col, value

有可能吗?怎么做?还有什么我可以尝试的吗?

1 个答案:

答案 0 :(得分:2)

您可以传入哈希值。请注意,要创建符号键,您需要调用ID2SYM(rb_intern(char*))表单,因为rb_intern会返回IDID2SYM会变成实际的Ruby符号。

VALUE kwargs = rb_hash_new();
rb_hash_aset(kwargs, ID2SYM(rb_intern("name")), rb_str_new2(name));
// ... 
rb_funcall(Word_Class, ID2SYM(rb_intern("new")), 1, kwargs);