Функции копирования

Основным обобщением между всеми glib типами (базовыми и небазовыми, классофицированными и неклассофицированными, instantiable и non-instantiable) является то, что ими можно манипулировать через единственный API для копирования и создания типов.

Структура GValue используется как абстрактный контейнер для всех этих типов. Её упрощенный API (определён в gobject/gvalue.h) может использоваться для вызова value_table функций в течение регистрации типа: например g_value_copy для копирования содержимого GValue в другой GValue. Это подобно назначению в C++, когда вызывается оператор копирования C++, чтобы по умолчанию побитно модифицировать копию семантики C++/C структур/классов.

Следующий код демонстрирует как можно копировать 64 битное целочисленное, так же как экземпляр указателя GObject (код этого примера находится в исходном пакете этой документации в sample/gtype/test.c):

static void test_int (void)
{
  GValue a_value = {0, }; 
  GValue b_value = {0, };
  guint64 a, b;

  a = 0xdeadbeaf;

  g_value_init (&a_value, G_TYPE_UINT64);
  g_value_set_uint64 (&a_value, a);

  g_value_init (&b_value, G_TYPE_UINT64);
  g_value_copy (&a_value, &b_value);

  b = g_value_get_uint64 (&b_value);

  if (a == b) {
    g_print ("Yay !! 10 lines of code to copy around a uint64.\n");
  } else {
    g_print ("Are you sure this is not a Z80 ?\n");
  }
}

static void test_object (void)
{
  GObject *obj;
  GValue obj_vala = {0, };
  GValue obj_valb = {0, };
  obj = g_object_new (MAMAN_BAR_TYPE, NULL);

  g_value_init (&obj_vala, MAMAN_BAR_TYPE);
  g_value_set_object (&obj_vala, obj);

  g_value_init (&obj_valb, G_TYPE_OBJECT);

  /* g_value_copy's semantics for G_TYPE_OBJECT types is to copy the reference.
     This function thus calls g_object_ref.
     It is interesting to note that the assignment works here because
     MAMAN_BAR_TYPE is a G_TYPE_OBJECT.
   */
  g_value_copy (&obj_vala, &obj_valb);

  g_object_unref (G_OBJECT (obj));
  g_object_unref (G_OBJECT (obj));
}

Важно в выше представленном коде то, что точная семантика вызова копирования не определена так как зависит от реализации функции копирования. Определённые функции копирования могут решить распределить новый участок памяти и зтем скопировать данные из источника в адресат. Другие могут просто увеличить количество ссылок на экземпляр и скопировать ссылку в новый GValue.

value_table определённый в gtype.h используется для определения этих функций и полностью описан в документации API поставляемой с GObject (for once ;-) это объясняет почему мы не будем детализировать точную семантику.

Маловероятно что вы будете когда либо определять value_table в процессе регистрации типа потому что value_tables наследуется из родительского типа для небазовых типов, это значит что если вы хотите создать базовый тип (не очень хорошая идея!), вам не потребуется обеспечить новый value_table так как вы унаследуете структуру value_table из родителя вашего типа.

[2] Пожалуйста помните что есть другие функции регистрации: g_type_register_dynamic. Мы не будем обсуждать эту функцию здесь, так как её использование очень похоже на версию _static.

Last updated

Was this helpful?