加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長期合作伙伴
立即加入
  • 正文
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

一個(gè)面向?qū)ο蟮腃語言框架!

11/27 15:30
1185
閱讀需 15 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

GObject是Glib庫的一部分,提供了一個(gè)靈活的、可擴(kuò)展的、并且容易映射到其他語言的面向?qū)ο蟮腃語言框架。以下是GObject的一些核心概念和使用方法。

源碼:https://gitlab.gnome.org/GNOME/glib/

教程:https://docs.gtk.org/gobject/index.html

1. GObject的核心概念

動(dòng)態(tài)類型系統(tǒng):GObject允許程序在運(yùn)行時(shí)進(jìn)行類型注冊,這意味著可以使用純C語言設(shè)計(jì)一整套面向?qū)ο蟮?a class="article-link" target="_blank" href="/tag/%E8%BD%AF%E4%BB%B6/">軟件模塊。

內(nèi)存管理:GObject實(shí)現(xiàn)了基于引用計(jì)數(shù)的內(nèi)存管理,這簡化了內(nèi)存管理的復(fù)雜性。

屬性系統(tǒng):GObject提供了通用的set/get屬性獲取方法,使得屬性管理變得更加簡單。

信號(hào)機(jī)制:GObject內(nèi)置了簡單易用的信號(hào)機(jī)制,允許對(duì)象之間進(jìn)行通信

2. GObject的使用示例

在GObject中,類和實(shí)例是兩個(gè)結(jié)構(gòu)體的組合。類結(jié)構(gòu)體初始化函數(shù)一般被調(diào)用一次,而實(shí)例結(jié)構(gòu)體的初始化函數(shù)的調(diào)用次數(shù)等于對(duì)象實(shí)例化的次數(shù)。所有實(shí)例共享的數(shù)據(jù)保存在類結(jié)構(gòu)體中,而對(duì)象私有的數(shù)據(jù)保存在實(shí)例結(jié)構(gòu)體中。

GObject實(shí)例的結(jié)構(gòu)體定義如下:

typedef?struct?_GObject??GObject;
struct??_GObject
{
??GTypeInstance??g_type_instance;
??
??/*<?private?>*/
??guint??????????ref_count;??/*?(atomic)?*/
??GData?????????*qdata;
};

GObject類的結(jié)構(gòu)體定義如下:

struct??_GObjectClass
{
??GTypeClass???g_type_class;

??/*<?private?>*/
??GSList??????*construct_properties;

??/*<?public?>*/
??/*?seldom?overridden?*/
??GObject*???(*constructor)?????(GType??????????????????type,
?????????????????????????????????guint??????????????????n_construct_properties,
?????????????????????????????????GObjectConstructParam?*construct_properties);
??/*?overridable?methods?*/
??void???????(*set_property)????????(GObject????????*object,
?????????????????????????????????????????guint???????????property_id,
?????????????????????????????????????????const?GValue???*value,
?????????????????????????????????????????GParamSpec?????*pspec);
??void???????(*get_property)????????(GObject????????*object,
?????????????????????????????????????????guint???????????property_id,
?????????????????????????????????????????GValue?????????*value,
?????????????????????????????????????????GParamSpec?????*pspec);
??void???????(*dispose)?????????(GObject????????*object);
??void???????(*finalize)????????(GObject????????*object);
??/*?seldom?overridden?*/
??void???????(*dispatch_properties_changed)?(GObject??????*object,
?????????????????????????guint?????n_pspecs,
?????????????????????????GParamSpec??**pspecs);
??/*?signals?*/
??void???????(*notify)??????????(GObject????*object,
?????????????????????GParamSpec?*pspec);

??/*?called?when?done?constructing?*/
??void???????(*constructed)?????(GObject????*object);

??/*<?private?>*/
??gsize?????flags;

??gsize?????????n_construct_properties;

??gpointer?pspecs;
??gsize?n_pspecs;

??/*?padding?*/
??gpointer??pdummy[3];
};

以下是一個(gè)簡單的示例,展示了如何創(chuàng)建和使用GObject實(shí)例:

#include?<glib-object.h>

int?main?(int?argc,?char?**argv)?{
????GObject*?instance1,?*instance2;?//?指向?qū)嵗闹羔?
????GObjectClass*?class1,?*class2;??//?指向類的指針

????instance1?=?g_object_new?(G_TYPE_OBJECT,?NULL);
????instance2?=?g_object_new?(G_TYPE_OBJECT,?NULL);

????g_print?("The?address?of?instance1?is?%pn",?instance1);
????g_print?("The?address?of?instance2?is?%pn",?instance2);

????class1?=?G_OBJECT_GET_CLASS?(instance1);
????class2?=?G_OBJECT_GET_CLASS?(instance2);

????g_print?("The?address?of?the?class?of?instance1?is?%pn",?class1);
????g_print?("The?address?of?the?class?of?instance2?is?%pn",?class2);

????g_object_unref?(instance1);
????g_object_unref?(instance2);

????return?0;
}
The?address?of?instance1?is?0x55fb9141ad20
The?address?of?instance2?is?0x55fb9141ad40
The?address?of?the?class?of?instance1?is?0x55fb9141a350
The?address?of?the?class?of?instance2?is?0x55fb9141a350

在這個(gè)示例中,g_object_new 函數(shù)用于創(chuàng)建GObject實(shí)例,并返回指向它的指針。G_TYPE_OBJECT 是GObject基類的類型標(biāo)識(shí)符,所有其他GObject類型都從這個(gè)基類型派生。宏 G_OBJECT_GET_CLASS 返回指向參數(shù)所屬類變量的指針。g_object_unref 用于銷毀實(shí)例變量并釋放內(nèi)存。

實(shí)例1與實(shí)例2的存儲(chǔ)空間是不同的,每個(gè)實(shí)例都有自己的空間。兩個(gè)類的存儲(chǔ)空間是相同的,兩個(gè)GObject實(shí)例共享同一個(gè)類。

3. GObject的信號(hào)機(jī)制

GObject允許定義和使用屬性,以及發(fā)出和連接信號(hào)。這些特性使得GObject非常適合用于構(gòu)建復(fù)雜的軟件系統(tǒng),尤其是在需要組件間通信和屬性管理的場景中。

信號(hào)最基本的用途是實(shí)現(xiàn)事件通知。例如:創(chuàng)建一個(gè)信號(hào),當(dāng)調(diào)用文件寫方法時(shí),觸發(fā)文件變化信號(hào)。

創(chuàng)建信號(hào):

file_signals[CHANGED]?=?
??g_signal_newv?("changed",
?????????????????G_TYPE_FROM_CLASS?(object_class),
?????????????????G_SIGNAL_RUN_LAST?|?G_SIGNAL_NO_RECURSE?|?G_SIGNAL_NO_HOOKS,
?????????????????NULL?/*?closure?*/,
?????????????????NULL?/*?accumulator?*/,
?????????????????NULL?/*?accumulator?data?*/,
?????????????????NULL?/*?C?marshaller?*/,
?????????????????G_TYPE_NONE?/*?return_type?*/,
?????????????????0?????/*?n_params?*/,
?????????????????NULL??/*?param_types?*/);

帶信號(hào)機(jī)制的文件寫方法:

void
viewer_file_write?(ViewerFile???*self,
???????????????????const?guint8?*buffer,
???????????????????gsize?????????size)
{
??g_return_if_fail?(VIEWER_IS_FILE?(self));
??g_return_if_fail?(buffer?!=?NULL?||?size?==?0);

??/*?First?write?data.?*/

??/*?Then,?notify?user?of?data?written.?*/
??g_signal_emit?(self,?file_signals[CHANGED],?0?/*?details?*/);
}

用戶回調(diào)處理函數(shù)連接到信號(hào):

g_signal_connect?(file,?"changed",?(GCallback)?changed_event,?NULL);

4. 跨語言互通性

GObject被設(shè)計(jì)為可以直接使用在C程序中,并且可以封裝至其他語言,如C++、Java、Ruby、Python和.NET/Mono等,這使得GObject具有很好的跨語言互通性。

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

本公眾號(hào)專注于嵌入式技術(shù),包括但不限于C/C++、嵌入式、物聯(lián)網(wǎng)、Linux等編程學(xué)習(xí)筆記,同時(shí),公眾號(hào)內(nèi)包含大量的學(xué)習(xí)資源。歡迎關(guān)注,一同交流學(xué)習(xí),共同進(jìn)步!