在上一节的例子中简单提到了使用rb_define_method
来定义一个函数。在这一节来进行详细介绍。
首先,函数有两种类型:
然后,以下是rb_define_method
的基本用法:
rb_define_method(ClassObj, "name", c_function, num);
执行的结果是为ClassObj这个类定义一个名为name
的实例方法,对应的C函数为c_function,接收num个参数。
对于参数个数固定的情况,它对应的c_function
基本形式如下:
VALUE c_function(VALUE self, VALUE arg1, VALUE arg2)
{
// ...
}
其中self
为该方法的调用者,其余的均是该方法的参数。
可变参数又分为两种情况:传入的是C数组和传入的是Ruby数组。
对于第一种情况,它对应的c_function
基本形式如下:
VALUE c_function(int argc, VALUE *argv, VALUE self)
{
// ...
}
这种情况比较复杂。
argc
为传入参数的个数;argv
为传入参数的集合;self
为方法调用者。对于这种情况不要直接对argv
进行操作,而是使用rb_scan_args
方法:
rb_scan_args(argc, argv, format, ...);
rb_scan_args
是通过format
字符串指定的格式对argv
进行解析,当参数不匹配时会抛出异常。
下面通过与之等效的ruby代码来介绍一下format
的用法:
def foo( arg = nil )
rb_scan_args(argc, argv, "01", &arg);
这是定义了一个方法,有0个必须参数和1个可选参数;
def foo( &block )
rb_scan_args(argc, argv, "0&", &block);
这是定义了一个方法,需要一个block类型的参数;
def foo( *args )
rb_scan_args(argc, argv, "0*", &args);
这是定义了一个方法,可传入任意个数的参数;
def foo( arg, opt = nil, *args, &block )
rb_scan_args(argc, argv, "11*&", &arg, &opt, &args, &block);
最后这是对上面的整合。
这种情况比较简单,它对应的c_function
形式如下:
VALUE c_function(VALUE self, VALUE args)
{
// ...
}
这里所有的参数都放在ruby类型的数组args
中。