GObject基本用法

  • Post author:
  • Post category:其他




GObject基本用法

GObject为C语言提供了面向对象支持

安装:

sudo apt install libglib2.0-dev



GObject模拟类的封装

为数据类型名称添加一些前缀(PT格式:P——Program,T——数据类型),模拟命名空间

所谓数据封装,就是将低层次的元素组合起来,形成新的、高层次实体的技术

纯C语言实现双向链表:

#ifndef _PROGRAM_LINKEDLIST
#define _PROGRAM_LINKEDLIST

typedef struct _Program_Linkedlist
{
	struct _Program_Linkedlist *prev, *next;
	void *data;
}_Program_Linkedlist;

typedef struct Program_Linkedlist
{
	struct Program_Linkedlist *head, *tail;
}Program_Linkedlist;

#endif

使用了GObject模拟类的数据封装形式:

#ifndef _PROGRAM_LINKEDLIST
#define _PROGRAM_LINKEDLIST

typedef struct _Program_Linkedlist
{
	struct _Program_Linkedlist *prev, *next;
	void *data;
}_Program_Linkedlist;

typedef struct Program_Linkedlist
{
	GObject parent_instance;  //

	struct Program_Linkedlist *head, *tail;
}Program_Linkedlist;

typedef struct _ProgramLinkedListClass
{
	GObjectClass parent_class;
}ProgramLinkedListClass;

#endif

类是两个结构体的组合,一个是实例结构体,另一个是类结构体

上述的

Program_Linkedlist_t

是实例结构体,而

ProgramLinkedListClass

是类结构体,合称

ProgramLinkedList

实例结构体的第一个成员是

GObject

结构体,类结构体的的一个成员是

GObjectClass

结构体

它们分别是

GObject

类的实例结构体与类结构体

上述表述意为该类继承自

GObject

继承GObject类后可以:

  1. 基于引用计数进行内存管理
  2. 构建对象的构造函数和析构函数
  3. 设置对象属性的set/get函数
  4. 使用信号机制

对对象的实例化:

Program_Linkedlist *dlist = g_object_new(PM_TYPE_DLIST, NULL);

销毁实例

g_object_unref(dlist);


g_object_new

为对象的实例分配内存和初始化,然后将实例的引用计数设为1


g_object_unref

将对象的实例的引用计数减1,检测引用计数是否为0,是则释放空间


类的实例是对象,每个对象都有可能存在多个实例

实际上它们是同一个东西

呵呵

上述使用的

PM_TYPE_DLIST

是一个宏,其定义形式为:

#define PM_TYPE_DLIST (pm_dlist_get_type())

GType pm_dlist_get_type(void);

在C文件中,需要定义如下内容:

G_DEFINE_TYPE (Program_Linkedlist, pm_dlist, G_TYPE_OBJECGT)

void pm_dlist_init(Program_Linkedlist *self)
{
}

void pm_dlist_class_init(Program_LinkedlistClass *class)
{
}


G_DEFINE_TYPE

宏可以帮我们实现类的定义

第一个参数,是我们所定义的类的类名

第二个参数,是类的成员函数名称的前缀

第三个参数,是该类的父类


G_TYPE_OBJECT

指代

GObject

类的

g_object_get_type

函数

PT格式:


P_TYPE_T




p_t_get_type()

函数

提供

p_t_get_type

函数可以让GObject识别你定义的数据类型

该函数的作用是向GObject库提供PT类的相关信息

需要包含:类初始化函数,实例初始化函数



本文简单总结

首先,你需要一个头文件和一个C文件

头文件中需要有这些东西:

  1. 类结构体定义,其中父类需要放在成员的第一位
  2. 实例结构体定义,其中父类需要放在成员的第一位
  3. 定义宏

    P_TYPE_T

    ,这个宏等价于

    p_t_get_type

    函数

在C文件中需要有这些东西:


  1. G_DEFINE_TYPE

    宏,真正定义类,它的构造为:第一个参数为类型的名字,第二个参数是类的函数名的前缀,第三个参数是父类的

    P_TYPE_T

  2. 类的初始化函数

    p_t_class_init
  3. 实例的初始化函数

    p_t_init

一个简单的helloworld类:

类的头文件

#ifndef _PM_HELLOWORLD_H
#define _PM_HELLOWORLD_H

#include <glib-object.h>

#define PM_TYPE_HELLOWORLD (pm_helloworld_get_type())

typedef struct PMHelloWorld
{
	GObject parentInstance;
}PMHelloWorld;

typedef struct PMHelloWorldClass
{
	GObjectClass parentClass;
}PMHelloWorldClass;

#endif

GType pm_helloworld_get_type(void);

类的C文件

#include "class_C_1.h"

G_DEFINE_TYPE (PMHelloWorld, pm_helloworld, G_TYPE_OBJECT);

static void pm_helloworld_init(PMHelloWorld *self)
{
	g_print("Hello world!\n");
}

static void pm_helloworld_class_init(PMHelloWorldClass *class)
{
}

main文件

#include <stdio.h>
#include "class_C_1.h"

int main()
{
	// g_type_init(); g_type_init在2.36后可以自动执行

	PMHelloWorld *helloworld = g_object_new(PM_TYPE_HELLOWORLD, NULL);

	if (G_IS_OBJECT(helloworld))
		printf("这是一个GObject对象\n");
	return 0;
}

makefile文件

cflags=`pkg-config --cflags gobject-2.0`
libs=`pkg-config --libs gobject-2.0`

all:
	make main

main: main.o class_C_1.o
	gcc -o main main.o class_C_1.o $(libs)

main.o: main.c class_C_1.h
	gcc -c main.c $(cflags)

class_C_1.o: class_C_1.h class_C_1.c
	gcc -c class_C_1.c $(cflags)

clean:
	rm class_C_1.o main main.o

remake:
	make clean
	make all



版权声明:本文为weixin_45206746原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。