GObject基本用法

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

猜你喜欢

转载自blog.csdn.net/weixin_45206746/article/details/112385112
今日推荐