【问题标题】:How do I create a Date object in a Ruby C extension?如何在 Ruby C 扩展中创建 Date 对象?
【发布时间】:2017-01-09 18:02:17
【问题描述】:

我正在尝试做这样的事情,但我无法理解如何在我的 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;
}

我想要做的是将 vdate 作为字符串传递给 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

【问题讨论】:

  • 该代码等同于Date.new.parse,这可能不是您想要的。
  • 该代码甚至无法编译,所以我想要的只是新的 Date 对象,以便我可以相应地使用它。我一直在寻找某种例子,但没有运气,所以即使只是一个链接也会很酷。
  • 等待它编译,但我的测试有 NoMethodError: undefined method `new' for 18709:Fixnum

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


【解决方案1】:

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"));

【讨论】:

  • 是的!这看起来像我想要的。谢谢!而且您在这里为我指明了正确的方向,因为我不确定要查看哪些文档。再次感谢马特。
  • 一个警告是,只要我在调用该方法时在 Ruby 代码中的某处需要“日期”,它就可以正常工作。但是,一旦我删除了日期库,我就会得到“日期”:未初始化的常量日期(NameError)。所以我还没说完。这里的目标是让 C 代码初始化 Date 类。有更新吗?
  • 好吧,Matt 现在如何在我的 C 代码中需要 Date 库?我应该开始一个新问题吗?我们现在就看看是否有人在我这样做之前阅读了这些 cmets。不过谢谢你的回答。
  • @DouglasG.Allen 要求来自 C 的只是 rb_require("date");
【解决方案2】:

是的,多亏了马特,我现在有了:

/*
* 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 类。 :-( 哦,好吧,我正在学习。

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

calc_sun

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多