通用值容器

通用值容器

GValue 结构基本上是一个变量容器,它由一个类型标识符和该类型特定的值组成。在 GValue 结构内部,类型标识符始终确定相关值的数据类型。

要创建一个未定义的 GValue 结构,只需创建一个零填充的 GValue 结构。要初始化 GValue,请使用 g_value_init() 函数。未初始化的 GValue 不能使用。

一旦使用完 GValue,就必须调用 g_value_unset() 来确保释放与 GValue 相关的所有资源。

基本类型操作(如释放和复制)由存储在 GValue 中的类型 ID 关联的 GTypeValueTable 确定。其他 GValue 操作(如值之间的类型转换)由该界面提供。

以下示例程序中的代码演示了 GValue 的功能

#include <glib-object.h>

static void
int2string (const GValue *src_value,
            GValue       *dest_value)
{
  if (g_value_get_int (src_value) == 42)
    g_value_set_static_string (dest_value, "An important number");
  else
    g_value_set_static_string (dest_value, "What's that?");
}

int
main (int   argc,
      char *argv[])
{
  // GValues must be initialized
  GValue a = G_VALUE_INIT;
  GValue b = G_VALUE_INIT;
  const char *message;

  // The GValue starts empty
  g_assert (!G_VALUE_HOLDS_STRING (&a));

  // Put a string in it
  g_value_init (&a, G_TYPE_STRING);
  g_assert (G_VALUE_HOLDS_STRING (&a));
  g_value_set_static_string (&a, "Hello, world!");
  g_printf ("%s\n", g_value_get_string (&a));

  // Reset it to its pristine state
  g_value_unset (&a);

  // It can then be reused for another type
  g_value_init (&a, G_TYPE_INT);
  g_value_set_int (&a, 42);

  // Attempt to transform it into a GValue of type STRING
  g_value_init (&b, G_TYPE_STRING);

  // An INT is transformable to a STRING
  g_assert (g_value_type_transformable (G_TYPE_INT, G_TYPE_STRING));

  g_value_transform (&a, &b);
  g_printf ("%s\n", g_value_get_string (&b));

  // Attempt to transform it again using a custom transform function
  g_value_register_transform_func (G_TYPE_INT, G_TYPE_STRING, int2string);
  g_value_transform (&a, &b);
  g_printf ("%s\n", g_value_get_string (&b));

  g_value_unset (&b);
  g_value_unset (&a);

  return 0;
}

为了让 GValue 拥有(并内存管理)任意类型或指针,它们需要成为一个boxed 类型。以下示例显示了如何将类型为 MyStruct 的指针 mystruct 作为boxed 类型使用。

typedef struct { ... } MyStruct;
G_DEFINE_BOXED_TYPE (MyStruct, my_struct, my_struct_copy, my_struct_free)

// These two lines normally go in a public header. By GObject convention,
// the naming scheme is NAMESPACE_TYPE_NAME:
#define MY_TYPE_STRUCT (my_struct_get_type ())
GType my_struct_get_type (void);

void
foo (void)
{
  GValue *value = g_new0 (GValue, 1);
  g_value_init (value, MY_TYPE_STRUCT);
  g_value_set_boxed (value, mystruct);
  // [... your code ....]
  g_value_unset (value);
  g_free (value);
}