(译者注:这章的符号就是 Ruby 中的 Symbol 对象,顾名思义,它是一个充当符号的物件,用于变量名、方法名、常量名等各种需要标识符的地方)
mruby
C 源代码中的符号由mrb_sym
表示,它是uint32_t
的别名。
其中,低30位用作符号,而高2位用作flags,例如class.c
中出现的struct mt_elem
:
struct mt_elem {
union mt_ptr ptr;
size_t func_p:1;
size_t noarg_p:1;
mrb_sym key:sizeof(mrb_sym)*8-2;
};
我们为符号提供了如下的 C API。
mrb_sym mrb_intern(mrb_state*,const char*,size_t)
用字符串获取一个对应的符号。
mrb_sym mrb_intern_check_cstr(mrb_state*,const char*)
用一个以 NULL 结尾的 C 字符串获取一个对应的符号。
mrb_sym mrb_intern_str(mrb_state*,mrb_value)
用一个 Ruby 字符串对象获取一个对应的符号。
mrb_intern_lit(mrb_state*,const char*)
从一个 C 字符串字面量中获取一个对应的符号,第二个参数一定要是 C 字符串字面量才行,否则就会产生一个编译错误。也因为是字面量,所以这个函数并不会拷贝这个 C 字符串。
mrb_sym mrb_intern_check(mrb_state*,const char*,size_t)
用一个字符串获取一个对应的符号,如果该符号还没有被注册,那就返回0
。
这个函数还有两个变体,一个是
mrb_intern_check_str()
用于 Ruby 字符串对象;
还有一个mrb_intern_check_cstr()
用于 C 字符串。
const char *mrb_sym_name(mrb_state*,mrb_sym)
获取一个符号的 C 字符串表示。
const char *mrb_sym_name_len(mrb_state*,mrb_sym,mrb_int*)
获取一个符号的字符串表示以及其长度。
为了节省 RAM,mruby
可以在编译时就分配一些符号,你可以通过包含mruby/presym.h
并使用如下的宏来获得预分配的符号。
MRB_SYM(xor)
//=> xor (和名称完全一致的符号)MRB_SYM_B(xor)
//=> xor! (带叹号,用于方法名)MRB_SYM_Q(xor)
//=> xor? (带问号,用于方法名)MRB_SYM_E(xor)
//=> xor= (带等号,用于方法名)MRB_CVSYM(xor)
//=> @@xor (带两个@前缀,用于类变量)MRB_IVSYM(xor)
//=> @xor (带一个@前缀,用于实例变量)MRB_OPSYM(xor)
//=> ^ (由名称转换而来的操作符)对于 MRB_OPSYM()
, 请指定与运算符对应的名称 (参见 lib/mruby/presym.rb
中的 MRuby::Presym::OPERATORS
来获取名称)。
除此之外,只描述符号名称,不要包括前缀以及后缀的标点符号。
这些宏在编译时被转换成静态的符号 ID ,除非预分配符号被conf.disable_presym
禁用。在这种情况下,这些宏会被扩展成mrb_intern_lit
调用,因此 mruby 的状态参数是必须的,而上面的宏假定这个状态参数在当前上下文叫作mrb
,如果不是的话,你就要使用后缀为_2
的宏,如MRB_SYM_2
来传入mrb_state*
参数。
你可以通过在配置文件中调用conf.disable_presym
来禁用预分配符号特性。