Glib学习笔记(二)

你将学到什么

  • 如何实现Object的构造函数和析构函数
  • 如何在条件检测不允许的情况下终止对象创建

Object的构造函数

对象的构造函数是不允许失败,如果你需要一个允许失败的GObject构造函数,使用GIO库提供的GInitableGAsynclnitable接口(文章最后会有个例子说明)

G_DEFINE_TYPE_WITH_PRIVATE (ViewerFile, viewer_file, G_TYPE_OBJECT)

static void
viewer_file_class_init (ViewerFileClass *klass)
{
}

static void
viewer_file_init (ViewerFile *self)
{
  ViewerFilePrivate *priv = viewer_file_get_instance_private (self);

  /* initialize all public and private members to reasonable default values.
   * They are all automatically initialized to 0 to begin with. */
}

如果你需要指定构造属性(G_PARAM_CONSTRUCT_ONLY),首先在class_init()函数里面安装这些属性,然后重写类的set_property()get_property()方法,实现属性的获取和设置,如下:

enum
{
  PROP_FILENAME = 1,
  PROP_ZOOM_LEVEL,
  N_PROPERTIES
};

static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };

static void
viewer_file_class_init (ViewerFileClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);

  object_class->set_property = viewer_file_set_property;
  object_class->get_property = viewer_file_get_property;

  obj_properties[PROP_FILENAME] =
    g_param_spec_string ("filename",
                         "Filename",
                         "Name of the file to load and display from.",
                         NULL  /* default value */,
                         G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE));

  obj_properties[PROP_ZOOM_LEVEL] =
    g_param_spec_uint ("zoom-level",
                       "Zoom level",
                       "Zoom level to view the file at.",
                       0  /* minimum value */,
                       10 /* maximum value */,
                       2  /* default value */,
                       G_PARAM_READWRITE));

  g_object_class_install_properties (object_class,
                                     N_PROPERTIES,
                                     obj_properties);
}

Object的析构函数

Object对象在引用计数为0后会依次调用disposefinalize函数完成析构,如下:

struct _ViewerFilePrivate
{
  gchar *filename;
  guint zoom_level;

  GInputStream *input_stream;
};

G_DEFINE_TYPE_WITH_PRIVATE (ViewerFile, viewer_file, G_TYPE_OBJECT)

static void
viewer_file_dispose (GObject *gobject)
{
  ViewerFilePrivate *priv = viewer_file_get_instance_private (VIEWER_FILE (gobject));

  /* In dispose(), you are supposed to free all types referenced from this
   * object which might themselves hold a reference to self. Generally,
   * the most simple solution is to unref all members on which you own a 
   * reference.
   */

  /* dispose() might be called multiple times, so we must guard against
   * calling g_object_unref() on an invalid GObject by setting the member
   * NULL; g_clear_object() does this for us.
   */
  g_clear_object (&priv->input_stream);

  /* Always chain up to the parent class; there is no need to check if
   * the parent class implements the dispose() virtual function: it is
   * always guaranteed to do so
   */
  G_OBJECT_CLASS (viewer_file_parent_class)->dispose (gobject);
}

static void
viewer_file_finalize (GObject *gobject)
{
  ViewerFilePrivate *priv = viewer_file_get_instance_private (VIEWER_FILE (gobject));

  g_free (priv->filename);

  /* Always chain up to the parent class; as with dispose(), finalize()
   * is guaranteed to exist on the parent's class virtual function table
   */
  G_OBJECT_CLASS (viewer_file_parent_class)->finalize (gobject);
}

static void
viewer_file_class_init (ViewerFileClass *klass)
{
  GObjectClass *object_class = G_OBJECT_CLASS (klass);

  object_class->dispose = viewer_file_dispose;
  object_class->finalize = viewer_file_finalize;
}

static void
viewer_file_init (ViewerFile *self);
{
  ViewerFilePrivate *priv = viewer_file_get_instance_private (self);

  priv->input_stream = g_object_new (VIEWER_TYPE_INPUT_STREAM, NULL);
  priv->filename = /* would be set as a property */;
}

使用GInitable接口

通过G_DEFINE_TYPE_WITH_CODE宏替代G_DEFINE_TYPE来定义GType,然后使用G_IMPLEMENT_INTERFACE创建一个GInitable对象(GType类型为G_TYPE_INITABLE),并实现接口的init函数(接口的定义和实现参考笔记四),这样在init实现函数中,我们可以对对象创建预置环境进行检测,如果不条件不符合,返回False即可终止对象创建

G_DEFINE_TYPE_WITH_CODE(SpiceUsbDeviceManager,
    spice_usb_device_manager,
    G_TYPE_OBJECT,
    G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, spice_usb_device_manager_initable_iface_init));

    static void spice_usb_device_manager_initable_iface_init(GInitableIface *iface)
{
    iface->init = spice_usb_device_manager_initable_init;
}

static gboolean spice_usb_device_manager_initable_init(GInitable  *initable, GCancellable *cancellable, GError **err)
{
    /* 此处代码省略 */
    return FALSE;
}
原文地址:https://www.cnblogs.com/silvermagic/p/9087888.html