Example #1
0
const RGObjClassInfo *
rbgobj_lookup_class_by_gtype_full(GType gtype, VALUE parent,
                                  gboolean create_class)
{
    const RGObjClassInfo *info;
    RGObjClassByGtypeData data;

    info = rbgobj_lookup_class_by_gtype_without_lock(gtype, parent, FALSE);
    if (info) {
        return info;
    }

    if (!create_class) {
        return NULL;
    }

    data.gtype = gtype;
    data.parent = parent;
    data.create_class = create_class;

    rb_funcall(lookup_class_mutex, id_lock, 0);
    return (RGObjClassInfo *)rb_ensure(rbgobj_lookup_class_by_gtype_body,
                                       (VALUE)&data,
                                       rbgobj_lookup_class_by_gtype_ensure,
                                       (VALUE)&data);
}
Example #2
0
static VALUE
rbgobj_lookup_class_by_gtype_body(VALUE data)
{
    RGObjClassByGtypeData *cdata = (RGObjClassByGtypeData *)data;
    const RGObjClassInfo *cinfo;

    cinfo = rbgobj_lookup_class_by_gtype_without_lock(cdata->gtype,
            cdata->parent,
            cdata->create_class);
    return (VALUE)cinfo;
}
Example #3
0
const RGObjClassInfo *
rbgobj_lookup_class_by_gtype_full(GType gtype, VALUE parent,
				  gboolean create_class)
{
    RGObjClassByGtypeData data;

    data.gtype = gtype;
    data.parent = parent;
    data.create_class = create_class;

    if (create_class) {
	rb_funcall(lookup_class_mutex, id_lock, 0);
	return (RGObjClassInfo *)rb_ensure(rbgobj_lookup_class_by_gtype_body,
					   (VALUE)&data,
					   rbgobj_lookup_class_by_gtype_ensure,
					   (VALUE)&data);
    } else {
	return rbgobj_lookup_class_by_gtype_without_lock(gtype, parent,
							 create_class);
    }
}
Example #4
0
static VALUE
get_superclass(GType gtype)
{
    VALUE super_class;

    if (rbgobj_convert_get_superclass(gtype, &super_class))
        return super_class;

    switch (gtype) {
    case G_TYPE_PARAM:
    case G_TYPE_OBJECT:
        return cInstantiatable;
    case G_TYPE_BOXED:
        return rb_cObject;
    case G_TYPE_POINTER:
        return rb_cData;
    case G_TYPE_ENUM:
    case G_TYPE_FLAGS:
        return rb_cObject;
    default:
    {
        GType parent_type;

        parent_type = g_type_parent(gtype);
        if (parent_type == G_TYPE_INVALID) {
            return cInstantiatable;
        } else {
            const RGObjClassInfo *cinfo_super;
            cinfo_super =
                rbgobj_lookup_class_by_gtype_without_lock(parent_type,
                        Qnil,
                        TRUE);
            return cinfo_super->klass;
        }
    }
    }
}
Example #5
0
static const RGObjClassInfo *
rbgobj_lookup_class_by_gtype_without_lock(GType gtype, VALUE parent,
        gboolean create_class)
{
    GType fundamental_type;
    RGObjClassInfo* cinfo;
    RGObjClassInfoDynamic* cinfod;
    void* gclass = NULL;
    VALUE c;

    if (gtype == G_TYPE_INVALID)
        return NULL;

    cinfo = g_hash_table_lookup(gtype_to_cinfo, GUINT_TO_POINTER(gtype));
    if (cinfo)
        return cinfo;

    if (!create_class)
        return NULL;

    c = Data_Make_Struct(rb_cData, RGObjClassInfo, cinfo_mark, NULL, cinfo);
    cinfo->gtype = gtype;
    cinfo->mark  = NULL;
    cinfo->free  = NULL;
    cinfo->flags = 0;

    fundamental_type = G_TYPE_FUNDAMENTAL(gtype);
    switch (fundamental_type) {
    case G_TYPE_POINTER:
    case G_TYPE_BOXED:
    case G_TYPE_PARAM:
    case G_TYPE_OBJECT:
    case G_TYPE_ENUM:
    case G_TYPE_FLAGS:
        if (NIL_P(parent)) parent = get_superclass(gtype);
        cinfo->klass = rb_funcall(rb_cClass, id_new, 1, parent);
        break;

    case G_TYPE_INTERFACE:
        cinfo->klass = rb_module_new();
        break;

    default:
        if (NIL_P(parent)) parent = get_superclass(gtype);
        if (NIL_P(parent)) {
            fprintf(stderr,
                    "%s: %s's fundamental type %s isn't supported\n",
                    "rbgobj_lookup_class_by_gtype",
                    g_type_name(gtype),
                    g_type_name(fundamental_type));
            return NULL;
        }
        cinfo->klass = rb_funcall(rb_cClass, id_new, 1, parent);
    }

    cinfod = (RGObjClassInfoDynamic *)g_hash_table_lookup(dynamic_gtype_list,
             g_type_name(gtype));
    if (cinfod) {
        cinfo->mark = cinfod->mark;
        cinfo->free = cinfod->free;
        rb_define_const(cinfod->module, cinfod->name, cinfo->klass);
    }

    rb_hash_aset(klass_to_cinfo, cinfo->klass, c);
    g_hash_table_insert(gtype_to_cinfo, GUINT_TO_POINTER(gtype), cinfo);

    if (G_TYPE_IS_CLASSED(gtype))
        gclass = g_type_class_ref(gtype);

    if (G_TYPE_IS_INSTANTIATABLE(gtype) || G_TYPE_IS_INTERFACE(gtype))
        rbgobj_define_action_methods(cinfo->klass);

    if (G_TYPE_IS_INSTANTIATABLE(gtype)) {
        GType* interfaces = NULL;
        guint n_interfaces = 0;
        guint i;

        interfaces = g_type_interfaces(gtype, &n_interfaces);
        for (i = 0; i < n_interfaces; i++) {
            const RGObjClassInfo *iface_cinfo;
            iface_cinfo =
                rbgobj_lookup_class_by_gtype_without_lock(interfaces[i],
                        Qnil,
                        TRUE);
            rb_include_module(cinfo->klass, iface_cinfo->klass);
        }
        g_free(interfaces);
    }

    if (!rbgobj_convert_type_init_hook(gtype, cinfo->klass)) {
        switch (fundamental_type) {
        case G_TYPE_OBJECT:
            rbgobj_init_object_class(cinfo->klass);
            break;
        case G_TYPE_ENUM:
            rbgobj_init_enum_class(cinfo->klass);
            break;
        case G_TYPE_FLAGS:
            rbgobj_init_flags_class(cinfo->klass);
            break;
        case G_TYPE_INTERFACE:
            rbgobj_init_interface(cinfo->klass);
            break;
        default:
            rbgobj_convert_type_init_hook(fundamental_type, cinfo->klass);
            break;
        }
    }

    if (gclass)
        g_type_class_unref(gclass);

    return cinfo;
}