如何在Ruby C扩展中创建Date对象?

时间:2017-01-09 18:02:18

标签: c ruby class datetime ruby-c-extension

我试图做这样的事情,但我无法理解如何在我的C代码中使用Ruby内部。

static VALUE func_get_date_object(VALUE self, VALUE vdate){
VALUE rb_date;
VALUE date;
rb_date = rb_funcall(rb_intern("Date"), rb_intern("new"), 0);;
date = rb_funcall(rb_date, rb_intern("parse"), 0);
return date;
}

我想要做的是将日期作为字符串传递给Date.parse(' yyyy-mm-dd')

但首先我认为我需要知道如何在C中为Ruby创建或实例化一个新的Date类对象。我该怎么办呢?

我为该代码编写了一个测试。

def test_date
  assert_equal('', @t.date(@t_date_str))
end

输出

NoMethodError: undefined method `new' for 18709:Fixnum

2 个答案:

答案 0 :(得分:3)

rb_intern返回internal ID for the name "Date"。你想要的是与这个名字相关的实际类,你可以用rb_const_get

来实现
VALUE cDate = rb_const_get(rb_cObject, rb_intern("Date"));

然后,您可以使用rb_funcall创建Date类的新实例:

rb_date = rb_funcall(cDate, rb_intern("new"), 0);

由于您实际上想要调用Date.parse类方法,您可能想要做的是直接在类上调用parse

VALUE parsed = rb_funcall(cDate, rb_intern("parse"), 1, rb_str_new_cstr("2017-1-9"));

答案 1 :(得分:0)

是的,谢谢Matt我现在有:

/*
* call-seq:
*  date('yyyy-mm-dd')
*
* convert input string to Date object.
*
*/
static VALUE func_get_date(VALUE self, VALUE vdate){
  VALUE cDate = rb_const_get(rb_cObject, rb_intern("Date"));
  VALUE parsed = rb_funcall(cDate, rb_intern("parse"), 1, vdate);
  return parsed;
}

测试是:

class TestCalcSun300 < Test::Unit::TestCase # MiniTest::Test
  def setup
    @t = CalcSun.new
    @t_date_str = '2000-01-01'
    @t_date = Date.parse('2000-01-01')
  end

  def test_date
    assert_equal(@t_date, @t.date(@t_date_str))
  end
end

只要我在Ruby代码中需要'date',它就能很好用。但没有它我没有初始化任何Date类。 :-(哦,好吧,我正在学习。

这是一个仍在开发中的Ruby gem,但我会分享它以防有人想玩它。原始宝石很好,但它没有所有最新功能。 rubygems.org上的名称相同

calc_sun