Ruby C API`定义了吗? SomeConstant`相当于?

时间:2012-05-04 04:48:16

标签: c ruby ruby-c-extension

我正在尝试转换if条件:

unless defined? SomeConstant
  # do some stuff
end

成为本机C扩展的一部分。有人知道如何在C API中进行defined?谓词检查吗?

编辑|我想我可以调用:

rb_funcall(rb_cObject, rb_intern("const_defined?"), 1, rb_intern("SomeConstant"))

虽然这在语义上略有不同。

1 个答案:

答案 0 :(得分:3)

如果您浏览1.9.3来源,您会发现insns.def中已实施defined?

DEFINE_INSN
defined
(rb_num_t op_type, VALUE obj, VALUE needstr)
/* ... */
    switch (type) {
    /* ... */
      case DEFINED_CONST:
        klass = v;
        if (vm_get_ev_const(th, GET_ISEQ(), klass, SYM2ID(obj), 1)) {
            expr_type = "constant";
        }
        break;

所以当你defined? SomeConstant时,你会穿过那个大switch并最终调用vm_get_ev_const。该函数在vm_insnhelper.c

中定义
static inline VALUE
vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq,
                VALUE orig_klass, ID id, int is_defined)

这个功能恰好是静态的,所以你无法得到它。看起来vm_get_ev_const是根据rb_const_definedrb_const_defined_from来定义的,并且这些内容应该在您的C中提供,以便您可以尝试这些;但是你必须为那些找到合适的klass

或者您可以使用您的想法并使用Object.const_defined?。与此相关的一个问题是它不能用A::B这样的东西做正确的事情,你不得不说Object.const_defined? :A && A.const_defined? :B因为Object.const_defined? :'A::B'只会在你脸上抛出异常。这里的一般解决方案需要迭代和类查找。但是,如果您正在查看的类都在顶级命名空间中,那么简单的Object.const_defined?应该可以解决问题。

相关问题