3

次のif条件を変換しようとしています:

unless defined? SomeConstant
  # do some stuff
end

ネイティブ C 拡張の一部に。defined?C API で述語チェックを行う方法を知っている人はいますか?

編集 | 私は呼び出すことができると思います:

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

これは明らかにわずかに異なりますが、意味的には異なります。

4

1 に答える 1

3

defined?1.9.3 のソースをたどると、次のように実装されていることがわかります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)

その関数はたまたま静的であるため、取得できません。andvm_get_ev_constの観点から定義されているように見えますが、これらの両方が C で使用できるはずなので、それらを試すことができます。しかし、あなたはそれらのための権利を見つけなければならないでしょう.rb_const_definedrb_const_defined_fromklass

または、あなたのアイデアをそのまま使用することもできますObject.const_defined?。それに関する1つの問題は、それが正しいことをしないということA::Bです. ここでの一般的な解決策には、反復とクラス ルックアップが必要です。ただし、見ているクラスがすべて最上位の名前空間にある場合は、単純な方法でうまくいくはずです。Object.const_defined? :A && A.const_defined? :BObject.const_defined? :'A::B'Object.const_defined?

于 2012-05-04T07:51:29.693 に答える