#define R_CAST(st) (struct st*)
#define RBASIC(obj) (R_CAST(RBasic)(obj))
#define ROBJECT(obj) (R_CAST(RObject)(obj))
#define RCLASS(obj) (R_CAST(RClass)(obj))
#define RMODULE(obj) RCLASS(obj)
#define RFLOAT(obj) (R_CAST(RFloat)(obj))
#define RSTRING(obj) (R_CAST(RString)(obj))
#define RREGEXP(obj) (R_CAST(RRegexp)(obj))
#define RARRAY(obj) (R_CAST(RArray)(obj))
#define RHASH(obj) (R_CAST(RHash)(obj))
#define RDATA(obj) (R_CAST(RData)(obj))
#define RSTRUCT(obj) (R_CAST(RStruct)(obj))
#define RBIGNUM(obj) (R_CAST(RBignum)(obj))
#define RFILE(obj) (R_CAST(RFile)(obj))
In ruby, the contents of an object is expressed by a C structure, always handled via a pointer. A different kind of structure is used for each class, but the pointer type will always be VALUE (figure 1).
You guessed that struct RBasic has been designed to contain some important information shared by all object structures. The definition of struct RBasic is the following:
▼ struct RBasic
290 struct RBasic {
291 unsigned long flags;
292 VALUE klass;
293 };
(ruby.h)
flags are multipurpose flags, mostly used to register the structure type (for instance struct RObject). The type flags are named T_xxxx, and can be obtained from a VALUE using the macro TYPE(). Here is an example:
static inline int
#if defined(HAVE_PROTOTYPES)
rb_type(VALUE obj)
#else
rb_type(obj)
VALUE obj;
#endif
{
if (FIXNUM_P(obj)) return T_FIXNUM;
if (obj == Qnil) return T_NIL;
if (obj == Qfalse) return T_FALSE;
if (obj == Qtrue) return T_TRUE;
if (obj == Qundef) return T_UNDEF;
if (SYMBOL_P(obj)) return T_SYMBOL;
return BUILTIN_TYPE(obj);
}
#define TYPE(x) rb_type((VALUE)(x))
#define T_MASK 0x3f
#define BUILTIN_TYPE(x) (((struct RBasic*)(x))->flags & T_MASK)
VALUE str;
str = rb_str_new(); /* creates a Ruby string (its structure is RString) */
TYPE(str); /* the return value is T_STRING */
The names of these T_xxxx flags are directly linked to the corresponding type name, like T_STRING for struct RString and T_ARRAY for struct RArray.
The other member of struct RBasic, klass, contains the class this object belongs to. As the klass member is of type VALUE, what is stored is (a pointer to) a Ruby object. In short, it is a class object.