By Xinzhen (LoneStar) xinzhen@auvtech.com
BCBX
在经历了一系列失败的“跨平台”努力后,独立工具软件商 Borland 的最后希望寄托在了 C++BuilderX,这个工业级的重型 C++ 开发环境上。C++BuilderX 与先前的 BC 或 BCB 有着显著的不同。不仅仅在于其使用 Java 写的 IDE,更本质的特征在于其旗舰级的定位,使它终于获得了人们期待已久的、与“C++”这个词相称的特征:高度标准相容的语法,开放,兼容,独立于平台。
GTK+
GTK+ 是一个用于构建用户界面的跨平台工具箱。与其说是用户界面,更精确的描述应是一个“框架”,集成了开发一个图形界面程序所需的所有底层架构,如信号传递机制,异步 I/O,字符集与编码处理等。目前的稳定版是 2.2.4。随着功能不断提升,它的应用也日趋广泛。相对于别的商业级应用程序框架,这个库使用了极其宽松且对商业友好的 LGPL 许可证,使它获得了越来越多的重视。
GTK+ for Windows
然而,虽然 GTK 架构中有一层又一层的封装层,来最大限度地实现平台无关性,但其来自于 Unix 世界的本质使得其要运行于 Windows,仍然需要用户搭建复杂的环境来编译和设定。幸好,半“官方”的 Windows 移植发布版已经出现,位于 http://www.dropline.net/gtk/index.php。从这个网站上可以下载到编译好了的 GTK+ for Windows Runtime Environment 与 Development Environment(对应于 Linux 上 gtk2 及 gtk2-devel 包),以及如何在 VC 中使用此库的简单介绍,甚至还有如何制作安装程序的简介。
从此站上下载到的发行版内置了一个主题引擎 Wimp。当这个主题引擎运行于 Windows XP 时,会调用 Native 的 XP 主题 API,获取如颜色方案、字体和贴图等信息,从而获得一个与 XP 完全一致的 Look and feel。当然,如果不是 XP,就只能用模仿的方式绘制控件,但至少颜色还是一致的。
BCBX with GTK+
当 BCBX 1.0于去年底发布时,一来由于时间仓促,二来作为工业级产品,“图形界面”所占比重较小,总之其中并未携带任何用于协助图形用户界面 (GUI) 开发的元素。
BCBX 的开放性体现在,支持 3 个平台,5种不同编译器。Intel 及 Microsoft 的编译器都列为支持。最让人意外的是,GNU 的 GCC 也在列表中,并且将随安装程序一并自动装入你的系统,无需任何额外的下载、安装步骤,即可使用:
其版本显示为“GNU C++ version 3.2 (mingw special 20020817-1) (mingw32)”
这一特征不禁让我们产生联翩浮想。这意味着无数的,GNU 或 非 GNU的,open 的 sources 将有简单的方法可以在 Windows 上使用了。GTK+ 当然就是其中之一。
配置 GTK+ for Windows 环境
我们现在就安装上述的 GTK+ Windows 发行版。这个发行版有着漂亮的安装程序,从哪方面看都是标准的 Windows 应用程序。真正的“跨平台”,就要做到融入所在的平台中去,与其他应用有相同的外观和行为特征,成为 Native 的应用。那种自成一体,与环境格格不入的程序,不能叫跨平台,而是自己就是平台,且只能运行于自己的平台上而已。
首先从这里下载 Runtime Environment。目前版本 2.2.4.1。
装上后,*.DLL 形式的动态库装入了 C:\Program Files\Common Files\GTK\2.0\lib中。为了让系统能找到它,我们需要为它设定 $PATH 环境变量。在 Windows 2000 上的设定方法是这样的。按组合键 Win+Pause,如果你没有 104 键 Windows 键盘(稀有动物)就只好在“我的电脑”(其实是你的,不是我的)上点右键,选属性。选 Advance 标签,点击 Environment Variables... 按钮。在对话框中寻找 Path 变量,没有的话新建一个。编辑其内容加入上述路径。
好,现在我们下载并安装 Development Environment。本例中我将它装到了 D:\GTK2DEV,后面的设定将以此为准。你可以自行酌情更改。
装好后,测试一下是否正常。去到目录 D:\GTK2Dev\share\gtk-2.0\demo 中,运行 gtk-demo.exe。如果看见界面,那么安装成功。
配置 BCBX 环境
GTK+ for Windows 站点上有很详细的如何在 Windows 上编译和运行的指令。但他们太复杂了,我通过在 BCBX 中新建一个项目,来 step by step 地简要描述一下。
STEP1:
我们在 BCBX 中新建一个项目,类型选择 New Console。
别急,我没搞错。尽管我们要开发的东西确实是 GUI的,我们选的也不是 New GUI Application,否则你就要为找不到 argc 和 argv 烦恼了。我将项目命名为 gtkhello。
STEP2:
现在,为了能编译这个项目,首先,我们教编译器去哪寻找 GTK+ 的头文件。在左上角项目名上点右键,选择“Build Options Explorer...”。在出现的对话框上部选择“MinGW GNU C++ Compiler”,在下部 Paths and Defines 标签中,include path 框里添加如下字符串:
d:\GTK2DEV\INCLUDE\GTK-2.0; d:\GTK2DEV\LIB\GTK-2.0\INCLUDE; D:\GTK2Dev\include\glib-2.0; d:\GTK2DEV\LIB\GLIB-2.0\INCLUDE; D:\GTK2Dev\include\pango-1.0; d:\GTK2DEV\INCLUDE\ATK-1.0; d:\gtk2dev\include
STEP3:
教我们的链接器如何链接对 GTK+ 程序的调用。在同一个对话框中,上部选择“GNU C++ Linker”,底下标签页中就会出现 library search path 框。在其中输入
D:\GTK2Dev\lib
在这个目录中存放着与每个 DLL 对应的 LIB 静态接口库。然后,我们转入 Options 页,在 Linker Options->Search for library LIBNAME 后面,输入如下字符串:
glib-2.0;gtk-win32-2.0;gdk-win32-2.0;gobject-2.0;gdk_pixbuf-2.0;gthread-2.0;gmodule-2.0;pango-1.0
这些就是所有接口库的名字。至此,所有设定完成。我们打开 2 年前登在 IBM developerWorks 网站上的 《GNOMEnclature: 为 GNOME 2 作好准备,第 1 部分 》一文,将“清单2”程序贴进我们刚刚生成的 untitled.cpp 中,从工具栏上点击 Make。编译过程应该很快就完成了。
STOP! Bitfields 与 对齐 align
CPU访问内存时,总是以其整数字长为单位读写。比如 x86 CPU 总是从4字节的整数倍数地址上,读取4字节数据,它不能随心所欲地从任何位置开始读取任意长度数据。为了效率考虑,默认情况下编译器总是让整数存放于其长度的整数倍数地址上。在一个结构中,为了做到这一点,有时不得不浪费几个字节。
举个例子,我们定义一个结构:
struct {
char c;
int i;
};
从字面上看,这个结构的长度是5个字节,但默认情况下编译器总是分配8个字节,是为了让 i 出现在偏移量 4 地址上。
位域 bitfields 是 C 语言结构中的一个成员,可以指定该成员所占内存的位数 bit。然而,在位域的对齐方式上,GCC和MSVC这2个编译器产生了巨大的分歧。现在,我们将上面这个结构改成下面这样子:
struct {
char c; int b: 1;
int i;
};
我们在 c 和 i 中插入了一个只占 1 位内存的整数。在 GCC 中,我们测试该结构的长度,发现仍然是 8 个字节,就是说 b 利用了 c 和 i 间的空隙,而没有多占空间。然而在 VC 中我们会发现,结构长达 12 字节。也就是说 b 像其他所有整数一样,在4倍数地址上对齐了。
如果仅仅这样还好办,不幸的是,如果你在b后面再插入一个位域 b2,长度还是12。而如果插入一个 short 型的位域,长度将变成16!
其原因在于 VC 使用了一种古怪的对齐方式,且没有完整的文档描述。基本上,VC 将结构中相邻的相同数据结构位域组成位域组,然后每个位域组都默认要求按其数据类型对齐。另外还有许多不同的例外情况。这样的情况与任何一个普通 GCC 支持的 对齐模式都不同。对齐方式不同意味着什么呢?考虑一下,Windows 是用 VC 编译的,也就是说所有 Windows API 都使用 VC 对齐方式。而如果你用 MinGW GCC编译 Windows 程序,你对所有使用了位域的 Windows API 的调用都将出错!而我们的 GTK+ for Windows 显然也是使用了这种对齐方式。
万幸的是,Windows 版 GCC 在编译时补上了一个新的命令行开关,-mms-bitfields,使其使用 VC 兼容的对齐方式。 Borland 所携带的这个 MinGW GCC也有。而这个开关别的平台上的 gcc 则都没有。加上这个编译开关后生成的代码将与 VC 的代码有相同的行为特征。只是 Borland 自己好像还没有意识到包里的 gcc 有着这么重要的一个开关,我找遍 Build Options Explorer 也没有找到有这个选项的勾可打。好在此时 BCBX 的开放性再次救了我们和它自己一命。在 Options 标签页的最下面,有一个 Other options and parameters 选项。填在里面的参数将被原封不动地拷贝到命令行上。所以我们在里面写上:
-mms-bitfields
OK,现在,激动人心的时刻就要到来了。按下 Run 按钮,我们的第一个 GTK 程序将运行了:
这是 Pango 标记的效果,与原文中的图比较一下。
这是 GTK 多页记事簿
至此,我们的 GTK+ for Windows 开发环境已经搭建成功了,剩下的就只需创意加上努力地 coding 了。
UTF-8, 到处都是 UTF-8
在结束本文前,我们最后看一个例子。《GTK+2.0编程范例》(清华大学出版社出版)一书的作者,宋国伟先生在应用GTK+编程一文中的一个 Helloworld 程序。在这个程序中,有这样一句语句:
g_signal_connect(G_OBJECT(button),"clicked", G_CALLBACK(on_button_clicked),(gpointer)"你好!\n自由的世界。");
程序本身并没有错,然而,在通常情况下,编译运行以后,并不能看见这句话,相反倒是在控制台上看见如
** (gtkhello.exe:1236): WARNING **: Invalid UTF8 string passed to pango_layout_set_text()
这样的字样。GTK 是一个国际化的工具箱,其内部所有地方都以 Unicode 存储字符串,亦可同屏显示任何语言。它要求所有输入的字符串都为 UTF-8 编码。然而“通常情况下”,我们编辑的中文文件都将以一个 locale encoding,比如 GB2312 编码,来保存。所以只要源文件能保存为 UTF-8,就解决了。BCBX 有这个能力。在cbx项目文件上点右键,选择属性。切换到 General 标签,将 Encoding 设为 UTF8。只有再新建的所有文件都将使用这里选中的编码来保存。
我们新建一个.c文件将内容复制过去。注意文件下方有 UTF8 字样。
然后再编译运行。
Happy Hacking!
文章就写到这里。本文是用 StarOffice 6 写的。说实话,非常的不好用。我常常被迫停下来与其搏斗,摆平后才能继续。最后创建的 html 质量很差,还有问题,得手工修改。
祝大家新年快乐
2004-1-4 4:14 AM