Разобраться в объектах gtk и их иерархии

На протяжении полугода изучал Си и теперь приступил к изучению GTK. У меня возникли вопросы, на которые я пока что не смог найти ответа.

  1. Правильно ли я понимаю, что объекты в gtk (например GtkWidget) являются по факту обычной структурой?

  2. Как понять "иерархия объектов"? Например GtkWidget > GtkContainer > GtkBin > GtkWindow. Значит ли это, что GTKWindow включает в себя все элементы структуры GtkBin и имеет еще свои уникальные? То есть это выглядит примерно так:

    struct GtkWindow {
        уникальные для GtkWindow элементы структуры;
        struct GtkBin _GtkBin
    };

A GtkBin в свою очередь так:

    struct GtkBin {
        уникальные для GtkBin элементы структуры;
        struct GtkContainer _GtkContainer
    };

И так далее или как это реализовано?

  1. Почему при создании нового окна с помощью gtk_window_new возвращается указатель на виджет, а не на окно? Ведь в gtk есть специальный объект для этого.

  2. Что происходит при преобразовании в другой тип с помощью макросов например так: GTK_WINDOW(mainwin). Создается новая срктура, в которую добавляются новые элементы, если mainwin это GtkWidget?


Ответы (1 шт):

Автор решения: KoVadim
  1. да, это структуры Простые обычные структуры. Просто оформлены по определенным правилам.

  2. Не нужно гадать, можно посмотреть в исходники.

    struct _GtkWindow
    {
       GtkBin bin;
    
       GtkWindowPrivate *priv;
    };
    

    только "базовая структура" указывается самой первой, что бы легко подсовывать "структуру наследника" там, где можно написать "родительскую структуру" (я специально в кавычки взял).

  3. Честно не знаю, но думаю, что это такое соглашение. Хотя мне кажется, так легче было сделать многие функции - они получают указатель на "базовую структуру" и типы сходятся. А кому нужно - вверх подымет.

  4. Обычный каст. Правда там ещё может быть и дополнительная проверка, что объект валидный. Опять же, можно посмотреть в сорцы

     #define GTK_WINDOW(obj)     (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WINDOW, GtkWindow))
     #define G_TYPE_CHECK_INSTANCE_CAST(instance, g_type, c_type)    (_G_TYPE_CIC ((instance), (g_type), c_type))
    
     /* --- implementation bits --- */
     #ifndef G_DISABLE_CAST_CHECKS
     #  define _G_TYPE_CIC(ip, gt, ct) \
         ((ct*) g_type_check_instance_cast ((GTypeInstance*) ip, gt))
     #  define _G_TYPE_CCC(cp, gt, ct) \
         ((ct*) g_type_check_class_cast ((GTypeClass*) cp, gt))
     #else /* G_DISABLE_CAST_CHECKS */
     #  define _G_TYPE_CIC(ip, gt, ct)       ((ct*) ip)
     #  define _G_TYPE_CCC(cp, gt, ct)       ((ct*) cp)
     #endif /* G_DISABLE_CAST_CHECKS */
    
→ Ссылка