A lot of types are not instantiable by the type system and do not have a class. Most of these types are fundamental trivial types such as gchar, registered in g_value_types_init (in gvaluetypes.c).

To register such a type in the type system, you just need to fill the GTypeInfo structure with zeros since these types are also most of the time fundamental:

  GTypeInfo info = {
    0,				/* class_size */
    NULL,			/* base_init */
    NULL,			/* base_destroy */
    NULL,			/* class_init */
    NULL,			/* class_destroy */
    NULL,			/* class_data */
    0,				/* instance_size */
    0,				/* n_preallocs */
    NULL,			/* instance_init */
    NULL,			/* value_table */
  };
  static const GTypeValueTable value_table = {
    value_init_long0,		/* value_init */
    NULL,			/* value_free */
    value_copy_long0,		/* value_copy */
    NULL,			/* value_peek_pointer */
    "i",			/* collect_format */
    value_collect_int,	/* collect_value */
    "p",			/* lcopy_format */
    value_lcopy_char,		/* lcopy_value */
  };
  info.value_table = &value_table;
  type = g_type_register_fundamental (G_TYPE_CHAR, "gchar", &info, &finfo, 0);
	  

Having non-instantiable types might seem a bit useless: what good is a type if you cannot instanciate an instance of that type ? Most of these types are used in conjunction with GValues: a GValue is initialized with an integer or a string and it is passed around by using the registered type's value_table. GValues (and by extension these trivial fundamental types) are most useful when used in conjunction with object properties and signals.