【发布时间】:2016-10-29 02:43:57
【问题描述】:
我正在为 Ruby 开发一个 C 扩展,我想调用一个需要关键字参数的方法,如下所示:
class Word
def initialize(line:, col:, value:)
end
end
在 C 语言中,我熟悉通过 rb_funcall 和 rb_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
有可能吗?它是如何完成的?还有什么我可以尝试的吗?
【问题讨论】:
-
我认为你应该能够只传递一个哈希(
rb_hash_new用于创建它,rb_hash_aset用于设置值)。让我知道这是否有效,然后我可以将其转化为答案。 -
感谢您的建议!我用我尝试过的一些东西更新了这个问题......还有其他方法可以尝试将哈希作为关键字传递吗?
-
您第一次尝试时就在正确的行上(将哈希作为最后一个参数传递),但键必须是符号,而不是 ID。试试
ID2SYM(rb_intern("name"))而不仅仅是rb_intern("name")。不知道有没有办法一步一步将C中的char *直接转成ruby符号,看来需要先创建一个ID再转成符号。 -
@matt 它有效!您能否将该建议添加为“答案”,以便我接受它并为您提供神奇的堆栈溢出点?
-
我认为@MichaelKohl 优先获得这些积分。
标签: ruby ruby-c-extension keyword-argument