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

How to pass keywords to a Ruby method from a C extension?

我正在为 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

可能吗?它是如何完成的?还有什么我可以尝试的吗?

你可以传入一个散列。请注意,要创建符号键,您需要调用 ID2SYM(rb_intern(char*)) 形式,因为 rb_intern returns 和 ID,其中 ID2SYM 变成实际的 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);