VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super) { VALUE klass; ID id; id = rb_intern(name); if (rb_const_defined_at(outer, id)) { klass = rb_const_get_at(outer, id); if (TYPE(klass) != T_CLASS) { rb_raise(rb_eTypeError, "%s is not a class", name); } if (rb_class_real(RCLASS_SUPER(klass)) != super) { rb_name_error(id, "%s is already defined", name); } return klass; } if (!super) { rb_warn("no super class for `%s::%s', Object assumed", rb_class2name(outer), name); } klass = rb_define_class_id(id, super); rb_set_class_path(klass, outer, name); rb_const_set(outer, id, klass); rb_class_inherited(super, klass); return klass; }
/* Foo = Numo::Struct.new { int8 :byte float64 :float, [2,2] dcomplex :compl } */ static VALUE nst_s_new(int argc, VALUE *argv, VALUE klass) { VALUE name=Qnil, rest, size; VALUE st, members; ID id; rb_scan_args(argc, argv, "0*", &rest); if (RARRAY_LEN(rest)>0) { name = RARRAY_AREF(rest,0); if (!NIL_P(name)) { VALUE tmp = rb_check_string_type(name); if (!NIL_P(tmp)) { rb_ary_shift(rest); } else { name = Qnil; } } } if (NIL_P(name)) { st = rb_define_class_id(name, klass); rb_funcall(klass, rb_intern("inherited"), 1, st); } else { char *cname = StringValuePtr(name); id = rb_intern(cname); if (!rb_is_const_id(id)) { rb_name_error(id, "identifier %s needs to be constant", cname); } if (rb_const_defined_at(klass, id)) { rb_warn("redefining constant Struct::%s", cname); rb_mod_remove_const(klass, ID2SYM(id)); } st = rb_define_class_under(klass, rb_id2name(id), klass); } rb_iv_set(st, "__members__", rb_ary_new()); rb_iv_set(st, "__offset__", INT2FIX(0)); if (rb_block_given_p()) { rb_mod_module_eval(0, 0, st); } size = rb_iv_get(st, "__offset__"); members = rb_iv_get(st, "__members__"); //printf("size=%d\n",NUM2INT(size)); rb_define_const(st, CONTIGUOUS_STRIDE, size); rb_define_const(st, ELEMENT_BYTE_SIZE, size); rb_define_const(st, ELEMENT_BIT_SIZE, rb_funcall(size,'*',1,INT2FIX(8))); OBJ_FREEZE(members); rb_define_const(st, "DEFINITIONS", members); rb_define_singleton_method(st, "new", rb_class_new_instance, -1); //rb_define_singleton_method(st, "[]", rb_class_new_instance, -1); rb_define_method(st, "allocate", nst_allocate, 0); return st; }
VALUE rb_define_class(const char *name, VALUE super) { VALUE klass; ID id; id = rb_intern(name); if (rb_const_defined(rb_cObject, id)) { klass = rb_const_get(rb_cObject, id); if (TYPE(klass) != T_CLASS) { rb_raise(rb_eTypeError, "%s is not a class", name); } if (rb_class_real(RCLASS_SUPER(klass)) != super) { rb_name_error(id, "%s is already defined", name); } return klass; } if (!super) { rb_warn("no super class for `%s', Object assumed", name); } klass = rb_define_class_id(id, super); st_add_direct(rb_class_tbl, id, klass); rb_name_class(klass, id); rb_const_set(rb_cObject, id, klass); rb_class_inherited(super, klass); return klass; }
VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super) { VALUE klass; ID id; id = rb_intern(name); if (rb_const_defined_at(outer, id)) { klass = rb_const_get_at(outer, id); if (TYPE(klass) != T_CLASS) { rb_raise(rb_eTypeError, "%s is not a class", name); } if (RCLASS_RUBY(klass)) { // Only for pure Ruby classes, as Objective-C classes // might be returned from the dynamic resolver. if (rb_class_real(RCLASS_SUPER(klass), true) != super) { rb_name_error(id, "%s is already defined", name); } return klass; } } if (!super) { rb_warn("no super class for `%s::%s', Object assumed", rb_class2name(outer), name); } klass = rb_define_class_id(id, super); rb_set_class_path(klass, outer, name); rb_const_set(outer, id, klass); rb_class_inherited(super, klass); return klass; }
/*! * Defines a class under the namespace of \a outer. * \param outer a class which contains the new class. * \param id name of the new class * \param super a class from which the new class will derive. * NULL means \c Object class. * \return the created class * \throw TypeError if the constant name \a name is already taken but * the constant is not a \c Class. * \throw NameError if the class is already defined but the class can not * be reopened because its superclass is not \a super. * \post top-level constant named \a name refers the returned class. * * \note if a class named \a name is already defined and its superclass is * \a super, the function just returns the defined class. */ VALUE rb_define_class_id_under(VALUE outer, ID id, VALUE super) { VALUE klass; if (rb_const_defined_at(outer, id)) { klass = rb_const_get_at(outer, id); if (TYPE(klass) != T_CLASS) { rb_raise(rb_eTypeError, "%s is not a class", rb_id2name(id)); } if (rb_class_real(RCLASS_SUPER(klass)) != super) { rb_name_error(id, "%s is already defined", rb_id2name(id)); } return klass; } if (!super) { rb_warn("no super class for `%s::%s', Object assumed", rb_class2name(outer), rb_id2name(id)); } klass = rb_define_class_id(id, super); rb_set_class_path_string(klass, outer, rb_id2str(id)); rb_const_set(outer, id, klass); rb_class_inherited(super, klass); rb_gc_register_mark_object(klass); return klass; }
/*! * Defines a top-level class. * \param name name of the class * \param super a class from which the new class will derive. * NULL means \c Object class. * \return the created class * \throw TypeError if the constant name \a name is already taken but * the constant is not a \c Class. * \throw NameError if the class is already defined but the class can not * be reopened because its superclass is not \a super. * \post top-level constant named \a name refers the returned class. * * \note if a class named \a name is already defined and its superclass is * \a super, the function just returns the defined class. */ VALUE rb_define_class(const char *name, VALUE super) { VALUE klass; ID id; id = rb_intern(name); if (rb_const_defined(rb_cObject, id)) { klass = rb_const_get(rb_cObject, id); if (!RB_TYPE_P(klass, T_CLASS)) { rb_raise(rb_eTypeError, "%s is not a class", name); } if (rb_class_real(RCLASS_SUPER(klass)) != super) { rb_raise(rb_eTypeError, "superclass mismatch for class %s", name); } return klass; } if (!super) { rb_warn("no super class for `%s', Object assumed", name); } klass = rb_define_class_id(id, super); rb_vm_add_root_module(id, klass); rb_name_class(klass, id); rb_const_set(rb_cObject, id, klass); rb_class_inherited(super, klass); return klass; }
VALUE build_class_from_descriptor(Descriptor* desc) { const char *name; VALUE klass; if (desc->layout == NULL) { desc->layout = create_layout(desc->msgdef); } if (desc->fill_method == NULL) { desc->fill_method = new_fillmsg_decodermethod(desc, &desc->fill_method); } name = upb_msgdef_fullname(desc->msgdef); if (name == NULL) { rb_raise(rb_eRuntimeError, "Descriptor does not have assigned name."); } klass = rb_define_class_id( // Docs say this parameter is ignored. User will assign return value to // their own toplevel constant class name. rb_intern("Message"), rb_cObject); rb_ivar_set(klass, descriptor_instancevar_interned, get_def_obj(desc->msgdef)); rb_define_alloc_func(klass, Message_alloc); rb_require("google/protobuf/message_exts"); rb_include_module(klass, rb_eval_string("::Google::Protobuf::MessageExts")); rb_extend_object( klass, rb_eval_string("::Google::Protobuf::MessageExts::ClassMethods")); rb_define_method(klass, "method_missing", Message_method_missing, -1); rb_define_method(klass, "respond_to_missing?", Message_respond_to_missing, -1); rb_define_method(klass, "initialize", Message_initialize, -1); rb_define_method(klass, "dup", Message_dup, 0); // Also define #clone so that we don't inherit Object#clone. rb_define_method(klass, "clone", Message_dup, 0); rb_define_method(klass, "==", Message_eq, 1); rb_define_method(klass, "hash", Message_hash, 0); rb_define_method(klass, "to_h", Message_to_h, 0); rb_define_method(klass, "to_hash", Message_to_h, 0); rb_define_method(klass, "inspect", Message_inspect, 0); rb_define_method(klass, "[]", Message_index, 1); rb_define_method(klass, "[]=", Message_index_set, 2); rb_define_singleton_method(klass, "decode", Message_decode, 1); rb_define_singleton_method(klass, "encode", Message_encode, 1); rb_define_singleton_method(klass, "decode_json", Message_decode_json, -1); rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1); rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0); return klass; }