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

要相信 GObject 是有用并且简单的!

Garfileo posted @ 2011年2月25日 08:07 in GObject 笔记 with tags glib GObject , 24160 阅读

去年,曾经用了 10 多天的时间学习了一番 GObject,当时疏于心得的总结,而现在已经忘记的差不多了。

最近因为观察到 GtkGLExt 项目没有跟进 gtk+-3.0 的意思,便想自己动手,丰衣足食,要么去改造现有的 gtkglext 代码,要么另起炉灶。也许在自由/开源的世界中,期待是可耻的,只有动手才会幸福。但是,这与 GObject 有什么关系?

在 GTK+ 的众多底层库中,GObject 与 GLib 是两块基石,在它们之上矗立着 Cairo、Pango、Clutter、GDK、ATK 等支柱,还有 GtkGLExt 这棵对我而言非常重要的小支柱,没有它我便不知道该如何在 GTK+ 中直接绘制 OpenGL 三维图形。事实上,除了 GtkGLExt 之外,还有 Cogl 可供选择,后者是对 OpenGL 进行抽象封装,主要是为了方便 Clutter 在其上层创造场景图结构。既然是封装,那么就需要容器,Cogl 所使用的容器便是 GObject。

也许你对 GTK+ 支持 OpenGL 的事情并不感兴趣,那么我们便将话题转回至 GObject,并提出这样一个问题:既然 GObject 如此重要,那么它究竟是做什么的?

简单的说,GObject 是一个程序库,它可以帮助我们使用 C 语言编写面向对象程序。

很多人被灌输了这样一种概念:要写面向对象程序,那么就需要学习一种面向对象编程语言,例如 C++、Java、C# 等等,而 C 语言是用来编写结构化程序的。事实上,面向对象只是一种编程思想,不是一种编程语言。换句话说,面向对象是一种游戏规则,它不是游戏。GObject 告诉我们,使用 C 语言编写程序时,可以运用面向对象这种编程思想。

从宏观层面上来论证 GObject 与 C++、Java 之类的面向对象编程语言相比具备何种优越性,这是没有意义的。最优化理论中有一个“没有免费的午餐”定理,大意是说没有一种方法可以适合于全部问题,应当选择合适的方法,并将它放在合适的地方使用。这个定理对于编程语言的选择与使用也有效,因为选择某种最合适的语言,本身就是一个最优化问题。

假如我们选择了 GObject,它最适合处理那些问题?

首先,与操作系统层面相距较近的程序设计,即系统程序设计,例如上文所列举的 GTK+ 及其支柱,使用 GObject 模拟的面向对象机制可以简化程序逻辑结构,同时还能保证程序的性能以及系统接口直接调用。最主要的是,系统程序员大都熟悉 C 语言,沟通较为方便。

其次,有时为了兼顾程序性能与开发效率,会对程序结构进行分层设计,底层模块采用 C 程序库实现,上层则使用动态语言或函数式语言实现,此时使用 GObject 除了可以简化底层模块的逻辑结构,还可以通过 GObject 与上层模块进行胶合。现在,GNOME 3 项目提供了 GObject Introspection 技术,专门用于处理 C + GObject 所实现的程序与上层动态语言或函数式语言的胶合问题 [1]。另外,GNOME 3 项目还实现了两种新的语言 Vala 和 Genie,前者语法类似 C#,后者语法类似 Python,使用它们所编写的程序源码,利用相应的编译器便可以生成 C + GObject 代码,进而可以编译为 C 程序[2, 3]

那么 GObject 容易掌握么?我认为它应该很容易学习和使用,就像网络上许多人很轻易的诟病它非常繁琐难用一样容易。在打算掌握任何一种技术之前,如果不相信它是简单的,内心深处便会滋生一种逃避的意识。我们也可以例证,如果 GObject 真的很难理解和应用,怎么会存在那么多基于 GObject 实现的程序,难道那些程序的作者皆为天才抑或疯子?这种概率实在太小了。

事实上,GObject 是被人为的复杂化了。因为很多学习 GObject 的人,一上来就奔着要全面洞悉 GObject 的实现原理与细节,但是又缺乏足够的耐心和基础知识。如果换一个角度来考虑这个问题,作为初学者,在学习 C++、Java 之类的面向对象编程语言之时,我们有打算直接潜心理解这些语言的内部实现吗?我们大都是要从 Hello world 之类的示例起步的。对于 GObject 的学习也应当如此。

~ END ~


参考文档

[1GObject Introspection 带来一些希望

[2vala, vala!

[3人生苦短,我用 Genie

转载时,希望不要链接文中图片,另外请保留本文原始出处:http://garfileo.is-programmer.com

pingf 说:
2011年2月25日 12:03

GObject是有用的,但还是坚持认为这个不简单,
一是概念太多[很多概念只是象征性的模拟,而且有很多时候用不到],不简单,
二是使用不便[从写一个类的代码量就知道了],不简单,
三是文档写的也不简单
四是学习曲线不简单
[这里补充说明下,我个人的关于编程语言难以的观点,
复杂的有C++,LISP(不大众语法,需要额外基础知识)等
简单的有python,c,php
适中的有Java,c#
既简单又复杂的有Ruby
]
怎么会存在那么多基于 GObject 实现的程序,难道那些程序的作者皆为天才抑或疯子?
个人觉得是因为这个足够规模了,
另外很多基于这个的库只是用了其中很小一部分的功能,更多用到的是GLib的功能,比如那个Clutter,
其源码中用到GObject的是很有限的,很少高级的技巧
不过如果用Vala写个稍微大点的东西,在看其生成的C代码,就比较恶心了

还有那个GObject introspection好像有很长时间了,一年前就见到过,
不过不知那种实现算不算是dsl的范畴了....

Avatar_small
Garfileo 说:
2011年2月25日 20:11

@pingf:

1. 概念再多,也不会多过 python、C 和 php,而且一般用户是不需要完全理解所有概念,应当只取所需

2. 使用不便,可以自己写代码生成器或者用编辑器提供的扩展

3. 文档不简单,是事实,否则我就没必要再写这一系列的文档了

4. 学习曲线很简单,只要了解 C 结构体、指针和函数指针就可以

5. cogl 的确只用了 gobject 一小部分的技能,其实那正是 gobject 开发者所希望的

6. GI 只是开发了很长时间,但它还是是 gnome 3 项目的一部分,直到最近,才有足够多的库支持它

7. 既然用了 vala,为啥还非要去看它生成的 C 代码呢?用 C 的人,很少去看 C 生成的汇编代码。

lemonhall 说:
2011年2月26日 02:14

Clutter这个库让我心存疑虑啊,INTEL和NOKIA合作搞得MEEGO的基石项目,可是NOKIA倒了,这下变成INTEL一家推这个项目了,而我对INTEL的软件历来没信心。

最后的结论是,GNOME3站在了一个不稳定的东西之上。

GObject是恶心人的东西,绝对不用。除非用Vala封装之~~

用Vala封装后的GObject没什么好讲解的了。

Avatar_small
Garfileo 说:
2011年2月26日 03:37

@lemonhall: 除了 meego 和 gnome 3 在用 clutter 之外,google 的 Chrome OS 也在用它做 WM。

lemonhall 说:
2011年2月26日 04:40

仔细又看了看Clutter的文档,真得是很缺失文档,Clutter Cookbook只有C语言的版本,看起来很费劲儿。

Chrome OS本身我都持怀疑态度【原谅我,我是个怀疑派】,不过说实话,有了GOOGLE在用多少能多一些安全感。

不过又看了很多视频,发觉Clutter还是很给力的,很多GNOME3的特效我以为都是那个Compiz弄出来的,现在学了Vala之后才明白,Gnome3是基于Clutter的。

动画效果真给力,翻页,页面消失。MeeGo果然原本就是为移动设备定制的东西,视觉效果很重要。 现在想起来MeeGo死了,真得很可惜。他不死,Clutter的开发动力会强劲得多!~

资料太少了,哎.....狠不下心去直接啃C版本的Clutter资料。

pingf 说:
2011年2月26日 07:32

@lemonhall:
现在Clutter的文档还不错啦,比着0.x时候的文档好的太多了,
虽然我也觉得Clutter不错,
但从Qt4.x引入QML等方便制作动画效果的东西后就觉得这个没啥优势了....

lemonhall 说:
2011年2月26日 09:48

@pingf:
^_^,是这样的嘛,我没用过QT,所以不懂。因为是C#出身,KDE之前在我大学时代的机器上跑不动,所以最后投奔了GNOME。。。

这么多年过去了,忽然之间看了Vala/Clutter/Mx toolkits,着实被惊艳了一把。

Avatar_small
纵横天下 说:
2011年3月07日 22:30

在个人用GObject写了个小例子后,发现GObject完全不适用于小库,相对于大型库才显得简单。

Avatar_small
Garfileo 说:
2011年3月07日 22:35

@纵横天下:

对的。

我在那篇“GObject 子类私有属性的外部访问”里有类似感慨:

内建支持面向对象的编程语言、动态编程语言以及函数编程语言,它们所提供的语法越高级,那么它们等价的 C 代码量便会越庞大。

如果你所解决的问题,需要很多层的数据抽象,如果使用 C 语言的话,就不得不写很多的模拟代码。倘若这些模拟代码在你全部代码所占的比重超过了你的容忍限度,可以考虑换一种更合适的编程语言。当然,你不可能是先用 C 写完代码后,再去评估那部分模拟代码所占的比重,但是这并不妨碍你凭借现有的经验去粗略估计。

我将 gtk+ 作为使用 C 语言应用的典范,gtk+ 3.0 的全部代码大约 515500 行,而 GObject 的代码大概 20000 行,其所占比重大约为 4%,这其中还不算 GTK+ 的那些基于 GObject 的底层库的代码量。我觉得 GTK+ 开发者使用 GObject 实现足够的面向对象支持,是比较划算的。

Heiher 说:
2011年3月13日 20:07

我存在一个疑问,GObject 将 C++ 在编译期做的事放到了运行时做,这样是否会影响其运行效率?

Avatar_small
Garfileo 说:
2011年3月13日 20:39

会影响效率。

首先是继承。GObject 不适合很多层次的继承,如果只是寥寥几层继承的话,那点影响可以忽略不计。

其次是类型识别。如果是基本类型,那么类型识别直接通过二进制移位计算来实现,效率损失算是微乎其微。如果是 GObject 的派生类,那么类型识别好像是通过查询继承列表来获取的,继承的越深,效率便越受影响。

Avatar_small
纵横天下 说:
2011年3月30日 21:32

C++也不止是在编译时,如虚函数需要在运行时创建虚函数表(v-table)

这个是每个C++书都会讲到的……

Avatar_small
纵横天下 说:
2011年3月30日 21:34

我没研究过GObject,但是只是觉得,GObject的类型用GType管理,而基本实现却是Has-A的OO格式,所以这个表应该不会很大(就好像GTK继承很深也没见效率比QT低多少)

黑暗诗人 说:
2011年10月09日 16:33

很好,很强大,同时也是很迷茫,我是刚刚从事GTK+程序开发的,我做了几周都没用过gobject,但是我们老大却总是喜欢用gobject,就算是很小很简单的程序他也要使用gobject导致程序看起来很是复杂,没办法逼着我研究gobject面向对象系统,我看了你一部分文章很留言,有一些感触,但是真不知道到底什么样的程序用gobject,我主要是用GTK+和cairo库,麻烦大拿告诉我一下,

Avatar_small
Garfileo 说:
2011年10月09日 17:03

@黑暗诗人: 如果只是在 GTK+ 的末端写程序的话,也就是直接使用 GTK+ 或第三方提供的现有控件,那么 GObject 基本上是用不到的。但是如果你想自己定义一些 GTK+ 控件或者想在 gobject 基础上做一些面向对象的底层库,诸如 Cairo, Clutter 这样的库,那么就需要用到 GObject。

黑暗诗人 说:
2011年10月09日 17:12

恩,谢谢您了,我明白了许多,您的文章真的写的很好

黑暗诗人 说:
2011年10月09日 17:27

我发现gobject里面一个很大的难点就是类型转换宏太多又杂,而且没有找到好的参考手册,您是怎么看待这些宏的

Avatar_small
Garfileo 说:
2011年10月09日 17:34

@黑暗诗人: 类型转换宏实际上常用的只有 1 个,那就是当前对象要『调用』父对象的方法时,那么就用父对象的类型把它转换一下。

我在『http://garfileo.is-programmer.com/posts/25338.html』中的『经常要用到并且需要自己定义的宏』部分作了一点总结。

snyh 说:
2012年8月23日 11:59

"GObject 与 GLib 是两块基石,在它们之上矗立着 *** Cairo *** "...
Are you sure?

Avatar_small
Garfileo 说:
2012年8月23日 12:56

@snyh: 见 http://developer.gnome.org/

Avatar_small
balotejun 说:
2012年9月09日 20:29

博主用 GObject 和 Python 写过控件没?最近我在研究这个,没什么头绪。。。

Avatar_small
Garfileo 说:
2012年9月11日 09:46

@balotejun: 用 gobject 写共享库,然后生成 gi 信息,然后就可以用 pygobject 调用了。可参考我那篇 gobject-introspection 的介绍的文章

Avatar_small
balotejun 说:
2012年9月11日 10:42

@Garfileo: 谢谢指导 ~~

snyh 说:
2013年7月19日 14:47

@Garfileo: cairo和gobject根本就没有直接关系,也不存在谁在谁之上.

Avatar_small
rca 说:
2013年7月21日 11:12

@snyh:

嗯,我是作者,cairo 的确是错了,它只用了 glib。


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter