【问题标题】:Ruby C API `defined? SomeConstant` equivalent?Ruby C API`定义? SomeConstant 等价物?
【发布时间】:2012-05-04 04:48:15
【问题描述】:

我正在尝试转换 if 条件:

unless defined? SomeConstant
  # do some stuff
end

进入原生 C 扩展的一部分。有人知道如何在 C API 中进行 defined? 谓词检查吗?

编辑 |我想我可以调用:

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

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

【问题讨论】:

  • Object.const_defined? 可能与您将获得的一样好。实际的defined? 关键字在insns.def 中实现(查找DEFINE_INSN)并调用vm_get_ev_const,它在vm_insnhelper.c 中是静态的,因此无法访问。
  • 我认为你是对的,谢谢!你愿意这样回答吗? :)
  • 我记下了一些笔记,但它(当然)并不总是像Object.const_defined? 那样简单。当然。

标签: c ruby ruby-c-extension


【解决方案1】:

如果你追溯1.9.3的源码,你会发现defined?是在insns.def中实现的:

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? 应该可以解决问题。

【讨论】:

猜你喜欢
  • 2011-01-21
  • 1970-01-01
  • 1970-01-01
  • 2012-04-07
  • 1970-01-01
  • 1970-01-01
  • 2012-04-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多