请在此处添加计数器
Charles 1999.9
各位朋友,大家好,让大家久等了。本来可以早些提交设计方案的,可以因为长沙这几天天气 太热,大家都开空调,电压很低,没法使用电脑。而且热得头晕,唉。。。。。。
我在网上用过很多名字,实际上往往是申请免费电子邮件箱的时候为了避免冲突瞎想出来的,哈哈。 大家就叫我Charles好了。这个名字是我们的英语老师给起的,我还算满意。
我最早接触X Window环境下的界面开发工具包是在1996年。那时候我需要使用Motif制作一个简单的 界面。Motif的与MFC、OWL不同的思维方式引起了我的很大兴趣,在1996年下半年、1997年上半年, 我在DOS平台下自行实现了一些窗口元素。为了能够充分体会窗口系统的构成原理,没有使用任何 开发工具,直接写屏、直接访问键盘、直接访问鼠标驱动程序。尤其是1997年上半年写的第2版,自行 佩带了资源编译器。功能比较完善。到了今年(1999),我注意到了linux,实际上可以说是一见钟情。 因为它或许是我们中国人快速进入系统软件领域的唯一途径。起点当然就是本人的拿手戏,界面开发 工具了。于是就有了GIRL。
GIRL是图形界面表述语言(Graphic Interface Represent Language)的缩写,当然本人也很喜欢 GIRL了。:)
GIRL是描述性的、界面构件类说明语言。GIRL编译器编译GIRL源文件生成C/C++语言源文件,而后再 由C/C++编译器编译连接成GIRL静态或动态连接库。由于GIRL仅仅描述界面构件类,GIRL应用程序还需要 和C/C++语言代码相连接,以完成所需要的功能。为了使C/C++程序方便地访问GIRL源文件定义的类或 对象,GIRL还提供了一组面向C/C++语言的应用程序界面(SDK)。在GIRL源文件中,可以定义的对象有: 颜色、光标、字体、位图。C/C++程序可以通过SDK访问这些对象。但是不能够对这些对象进行任何修改。 此外,C/C++程序还可以利用SDK动态地创建颜色、光标、字体、位图对象,并动态地删除它们。
界面开发工具包在窗口系统中的重要地位,相信大家都已经十分清楚了。在设计GIRL之前,深入地 研究现有的经典GUI Tool Kit是绝对必要的。linux的开发方式告诉我们,闭门造车只有死路一条。 所以,为了把GIRL设计好(对于GUI Tool Kit来说,设计比实现重要得多,没有那个使用者希望工具包 随着版本的不同变来变去),我认为首先应该对设计方案进行充分的讨论,集思广益,使GIRL成为我们 大家共同的Daughter。
如果希望设计一个好的界面开发工具包,对界面应用程序规律的研究是必不可少的。在我编程的 实践中,感觉到现代图形界面应用程序的基本特征有:
对于某些应用程序,还需要注册空闲函数,在没有出现任何事件的情况下完成预定的操作。必要典型 的有:媒体播放器、游戏等等。
把上述特征与常用的开发工具包相比较,可以发现多数工具包在对界面应用程序工作的整个过程的 支持中,没有很好地利用界面元素的静态性。应用程序必须自行设计构造界面的过程、自行维护界面 数据之间约束关系。
虽然界面开发工具包不可能包办所有与界面相关的工作,但是尽可能地简化界面编程却是界面开发 工具包的主要任务。创建界面的过程,在应用程序代码中往往占据了相当大的比重。事实上应用程序的 使用者并不关心界面是如何创建的,界面元素是如何组织的。用户只对他们看到的东西以及软件提供的 功能感兴趣。同时,界面元素的创建具有很强的规律性,GIRL的一个重要目的就是:应用软件的开发者 只要给出静态界面构成的描述,就可以把一个复杂的、由多个构件构成的界面元素作为一个整体,进行 操作。在这个方面,Motif附带的应用程序UIL做出了一个很好的榜样。
Motif的UIL的功能的局限性,限制了它的应用范围。UIL除了帮助应用程序创建静态界面之外,没有 其他的功能。可是,应用程序还可以通过创建子程序的手段创建界面,虽然比UIL麻烦一些。对于作为 一个整体的组合界面,应用程序往往还需要:
只有对上述功能提供良好的支持,才能把大大地提高开发效率。真正发挥自动构造组合界面元素的优 势。否则,应用程序仍然需要深入组合界面元素内部,从而使开发工作复杂化、降低了模块的重用性。
GIRL必须完成的另一项重要任务就是定义数据之间的约束关系,并自动地维护、保持这个关系。
经过了上述分析,已经明确了GIRL需要完成的任务。那就是以描述的方式,描述组合界面对象的构成、 数据约束关系,并且给出统一的定义方式,遮蔽组合对象的构成和约束关系的细节。
GIRL是一种面向比较复杂的应用程序的独立语言。以描述的方式不可能实现软件的所有功能,GIRL 必须可C/C++语言分工合作,由GIRL完成界面的定义工作,由C/C++完成数据的具体处理任务。也就是说, GIRL必须可以和C/C++代码进行连接,从而构成整个应用程序。同时,类似与C/C++,为了提高开发效率, 必须允许构件的模块化,即GIRL模块的分别编译。在当前的设计中,应用程序主要按照如下方式使用 GIRL:
所谓的模块化问题,实际上包括:在不同的GIRL模块中定义的对象如何相互访问、C/C++程序如何 访问GIRL模块中定义的对象两个问题。C/C++语言为我们提供了一个良好的解决方案。
C/C++把对对象的说明和定义明确地分开。同一个对象可以在任何一个目标文件中进行说明,但是 任何一个对象却只能在一个目标文件中定义。
由于每个目标文件都含有它所需要的对象的说明,因此可以准确无误地使用其它目标文件定义的 对象。对对象的说明仅仅是告知编译器对象的类型,编译器将不会因为说明而生成任何代码。因此不会 导致代码的浪费。
由于只有一个目标文件含有对象的定义,因此不会出现多次定义同一对象而可能导致的冲突。编译器 只对象的定义生成相应的代码。
根据对象的说明和定义的上述区别,编程者就可以把说明写入头文件,在每个需要说明的源文件中 引入给定头文件;把定义写入源文件。而后再把每个源文件编译成目标文件。最后,在连接的时刻检测 不同目标文件中是否重复地定义了对象。如果没有冲突,就生成可执行文件。
GIRL的模块化采用了与C/C++完全类似的方式。关键是对每种对象给出对象的说明、对象的定义两种 方式。对象的说明含有的信息越少越好,但必须使得使用对象的其他对象可以正确地使用对象。对象的 定义则必须含有对象的全部细节。
C/C++还提供了一些库函数以支持Plug-in功能。在不同的平台上,库函数界面有所不同。对于linux 来说,主要是通过库函数:dlopen、dlerror、dlsym、dlclose四个函数来实现的。GIRL支持Plug-in的 方式和C/C++的方式完全类似,详情暂略。
GIRL定义的核心对象是组合构件类。组合构件类应当含有如下信息:
为了很好地完成上述任务,GIRL构造的专用的说明语言。
GIRL中的构件类的成员可以由四种成分构成,它们分别是:数据储存槽(dataslot)、数据接收槽 (receiver)、信号连接槽(signallink)、私有数据空间。
从某种意义上说,数据储存槽是数据接收槽的一种特例。数据储存槽是仅仅能够储存一个数据的 储存单元。而数据接收槽则可以储存复杂的数据结构,并在储存和读出的过程中进行特定的处理。
数据储存槽、数据接收槽可以接收的数据可能有:整数、浮点数、字符串、颜色、光标、字体、构件。 那么,在GIRL中就必须允许定义这几类数据。此外,还可以定义由上述数据组合起来的组合结构。
综上所述,在GIRL中可以定义的对象类型有:整数对象、浮点数对象、字符串对象、颜色对象、 光标对象、字体对象、构件类。GIRL必须分别为这些对象提供说明和定义的手段。此外,类似与 C/C++,GIRL允许定义类型。类型只有定义形式,没有说明形式。类型可以在多个模块中定义,这是因为 类型仅仅告知编译器组合数据的结构,而不生成任何代码。
GIRL要解决的一个重要问题就是确定组合构件类内部的数据约束。
通过考察可以发现,对于某些构件来说,有必要从其子构件中“继承”某些数据或功能。比如说对话框, 常见的方式是在创建对话框之后,为了获得或设置对话框中控制的数据,就必须访问对话框中的控制。 这样,除非我们单独定义一个类,并且在类的界面中给出访问特定控制的函数或数据成员,否则就不能 把对话框看作一个对象整体。然而,这样做通常是相当麻烦的。如果提供了数据约束手段,把组合构件中的 某个数据成员或者访问函数与子构件相应的数据成员、访问函数统一起来,那么就可以轻易地实现单一的 类界面,再也没有必要直接访问子构件了。
数据约束的另一大好处是简化数据相关关系的维护。比如说:某个控制的背景颜色必须和另一个控制 的背景颜色相同;某个控制中储存的整数值必须小于另一个控制中储存的整数值。
在GIRL的设计中,提供数据储存槽、数据接收槽的目的就是为了支持数据约束的功能。应用程序只有 间接地访问数据储存槽、数据接收槽(通过数据储存槽访问函数、数据接收槽的接收、读出函数),才能 给系统以维护约束关系的机会。
可能存在的数据约束有:
在上述关系中,应用范围最广泛的、最容易实现的是相等关系。在GIRL中,连接就是认定数据相等的 手段。连接可以在数据储存槽与数据储存槽之间、数据连接槽与数据连接槽之间、数据储存槽和数据 连接槽之间进行。
在本设计中,没有给出说明算术整数关系的表述方式。如果引入算术整数关系,那么只能适用于数据 储存槽。需要指出的是算术整数关系的维护比较复杂,必须区分连接与被连接的区别,
例1:对于关系X>=Y。其中X、Y都是整数类型数据储存槽。考虑如下情况:
例2:对于关系X=Y+1。其中X、Y都是整数类型数据储存槽。考虑如下情况:
例3:对于关系X=Y/3。除了前面需要考虑的情况之外,还有:如果X被修改的话,事实上Y可能的值有3个。 如果处理这种情况?
不难看出,一旦允许出现算术关系,可能导致为了维护数据约束关系而必须解方程组的情况。为此,GIRL 没有支持这种功能。
浮点数的算术关系类似与整数的算术关系。此外,还必须考虑浮点数计算的误差问题。
字符串的比较关系、连接关系类似于算术整数关系。但事实上字符串的比较关系、连接关系的应用很少, 而且效率很低。如果必须应用的话,由构件或应用程序用C/C++来实现往往效率更高一些。因此,GIRL没有 支持这种功能。
给出前面描述的目的是说明为什么要以一种相当特别的方式定义GIRL。事实上,GIRL与常见的GUI Tool Kit的表述方式有很大的不同。
GIRL的设计分以下几个部分:
使用自行实现的类机制主要好处有:
这是因为一旦使用了算术约束,将导致需要大量运算的解线性代数方程组的工作,大大地降低了运行效率。 此外,即使未来需要添加算术约束,也可以在兼容现有语法的前提下,添加新语句实现算术约束。
GIRL的库函数将按照库通用公共许可证(LGPL)发布。GIRL的编译器girlc及其他工具程序将按照 通用公共许可证(GPL)发布。
由于本设计方案仍然是草案,为了维护作者的名誉,请不要在未与作者商议的情况下发布本设计方案。
本设计方案将根据讨论的情况进行适当的修改,作者Charles保留修改权。在基本定稿之后即开始开发 工作。在开发工作进行的过程中,可能还会对设计的某些细节进行修改,但是GIRL的设计思想将不会发生 变化。
本人欢迎任何形式的,有关GIRL设计的建议与提问。由于条件的限制,最便捷的方式是发送电子邮件到 这里。所有有价值的建议,都将在本主页更新中独立地给出。
如果您需要本主页的压缩包,可以通过电子邮件和本人联系,以便于离线浏览。
对于您对GIRL的关心表示感谢
欢迎您参加对GIRL设计方案的讨论
欢迎您参加实现GIRL的工作
Charles 1999.9