一、文档目的
通过阅读这个文档,可以让你完成一个GTK+应用程序的编译、运行和调试。
二、GTK+简介
GIMP是UNIX类操作系统上的影像处理程序。GIMP是能用影像处理程序(Gerneral Image Manipulation Program)或者GNU影像处理程序(GNU Image Manipulation Program)的缩写。它是开放源代码软件,可以从Web站点 www.gimp.org上得到其源代码。
GTK+表示GIMP工具集(GIMP Toolkit,GTK)。GTK+是工具库,最早用于GIMP的开发。这是为什么将GTK+称为GIMP工具集的原因。GIMP也成为专业人员使用GTK+开发的图形用户界面应用的范例。
虽然GTK+最早用于GIMP的开发,但它现在广泛用于开发Linux的图形用户界面(GUI)应用。GTK+是开放源代码的工具库。用户可以按LGPL(库通用公共许可证)的条款使用它。在其他支持GTK+库的平台上也可以用它来开发GUI应用。
GTK+库是用C语言写成的面向对象的库,它支持用多种语言编写的应用软件。支持的语言包括:Ada95、C++、Eiffel、Objective C、Pascal、Perl、Python等。可以从GTK+的Web站点 www.gtk.org查到支持的语言的最新清单。
三、一个GTK+的源程序
首先,使用你所喜爱的编辑器写一个GTK+的源程序。这个文档不是讲如何写GTK+的应用程序,所以你可以直接复制使用下面这个源程序。
引用
/*
* The program's name is hellogtk+.c
*/
#include <unistd.h>
#include <gtk/gtk.h>
static GtkWidget *entry;
void
PrintAndExit (GtkWidget *widget, GtkWidget *window)
{
char *str;
str = gtk_entry_get_text(GTK_ENTRY(entry));
if (str != (char *) NULL)
printf("%s\n", str);
gtk_widget_destroy(window);
gtk_main_quit ();
}
void
PrintByeAndExit (GtkWidget *widget, gpointer data)
{
printf( "Goodbye, World!\n" );
gtk_exit(0);
}
int
main( int argc, char *argv[] )
{
GtkWidget *window, *label,*vbox,*hbox,*button,*separator;
gtk_set_locale ();
gtk_init (&argc,&argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_policy(GTK_WINDOW(window),FALSE,FALSE,FALSE);
gtk_signal_connect (GTK_OBJECT(window), "destroy",
GTK_SIGNAL_FUNC(PrintByeAndExit),NULL);
gtk_window_set_title (GTK_WINDOW (window), "Hello Gtk+!");
gtk_container_border_width(GTK_CONTAINER(window), 0);
vbox = gtk_vbox_new (FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
hbox = gtk_hbox_new(FALSE, 0);
gtk_box_pack_start (GTK_BOX (vbox),hbox, FALSE, FALSE, 0);
label = gtk_label_new("Enter a message:");
gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0);
entry = gtk_entry_new ();
gtk_entry_set_text (GTK_ENTRY(entry), "");
gtk_editable_select_region(GTK_EDITABLE (entry), 0, -1);
gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
separator = gtk_hseparator_new();
gtk_box_pack_start (GTK_BOX(vbox), separator, FALSE, FALSE, 0);
button =gtk_button_new_with_label ("Print");
gtk_signal_connect_object (GTK_OBJECT(button), "clicked",
GTK_SIGNAL_FUNC(PrintAndExit),GTK_OBJECT(window));
gtk_box_pack_start(GTK_BOX(vbox),button,FALSE,FALSE, 0);
GTK_WIDGET_SET_FLAGS (button,GTK_CAN_DEFAULT);
gtk_widget_grab_default (button);
gtk_widget_show_all (window);
gtk_main();
return (0);
}
这个程序的功能是显示用户输入的一个字符串(当用户什么也没有输入时则什么也不显示)。
四、如何编译
在你编译这个GTK+源程序前,先使用下面的命令:
引用
# gtk-config --libs --cflags
# pkg-config gtk+-2.0 --libs --cflags
这两个命令是用来导出编译和连接GTK+应用程序时所需要的标志和参数。我使用的系统是Fedora1.0,得到下面的结果:
引用
-I/usr/include/gtk-1.2 -I/usr/include/glib-1.2 -I/usr/lib/glib/include
-I/usr/X11R6/include
-L/usr/lib -L/usr/X11R6/lib -lgtk -lgdk -rdynamic -lgmodule -lglib
-ldl -lXi -lXext -lX11 -lm
-I/usr/include/gtk-2.0 -I/usr/lib/gtk-2.0/include
-I/usr/include/atk-1.0 -I/usr/include/pango-1.0
-I/usr/X11R6/include -I/usr/include/freetype2
-I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include
-Wl,--export-dynamic -lgtk-x11-2.0 -lgdk-x11-2.0 -latk-1.0
-lgdk_pixbuf-2.0 -lm -lpangoxft-1.0 -lpangox-1.0 -lpango-1.0
-lgobject-2.0 -lgmodule-2.0 -ldl -lglib-2.0
如果你没有得到上面的任何一种,那么你就需要检查你输入的命令是否正确,或是检查你系统中是否安装了GTK+程序。
现在,你可以用下面的其中一个命令来编译你的GTK+应用程序了。
引用
# gcc -Wall -g -o hellogtk+ hellogtk+.c `gtk-config --libs --cflags`
# gcc -Wall -g -o hellogtk+ hellogtk+.c `pkg-config gtk+2.0 --libs --cflags`
注意:“ `”这个这符是位于你键盘ESC下面的那个键,不是单引号。
该程序运行结果如图所示:
http://timity.nease.net/documents/gtk+/images/hellogtk+.png
你可以在文本框内输入任何字符,然后按print按键,程序就会将你输入的字符打印到标准的输出设备上,然后退出。如果你什么也没有输入,那么程序也就什么也不打印。
五、写一个Makefile文件
如果你的程序运行正确,那你现在可以试着写一个简单的Makefile文件,它能使你编译过程变得简单。
引用
CC = gcc -Wall -g
CFLAGS = `gtk-config --cflags`
LDADD = `gtk-config --libs`
all : hellogtk+
hellogtk+ : hellogtk+.o
$(CC) $(LDADD) hellogtk+.o -o hellogtk+
hellogtk+.o : hellogtk+.c
$(CC) $(CFLAGS) -c hellogtk+.c -o hellogtk+.o
clean :
rm -f *.o hellogtk+
现在,就可以用命令make来编译你的程序了!
六、调试
先把PrintAndExit函数部分改为下面这样:
引用
void
PrintAndExit (GtkWidget *widget, GtkWidget *window)
{
char *str;
gtk_entry_get_text(GTK_ENTRY(entry)); /*这一行被改动*/
if (str != (char *) NULL)
printf("%s\n", str);
gtk_widget_destroy(window);
gtk_main_quit ();
}
然后照前面的编译方法编译源程序,之后运行,你会发现当你按下print按钮时,输出的会是一些奇怪的字符。
简单的程序,只要稍加检查就可以找到产生bug的原因。但许多时侯通过检查代码不能发现bug,这个时侯就需用到调试器了,如gdb。
要使用gdb,必须在编译程序的命令行里加入“-g”标志。并去除所有优化标志。得到二进制文件后,就可以执行下面的命令行调用gdb:
引用
# gdb hellogtk+
之后,应能看到下面的输出:
引用
GNU gdb Red Hat Linux (5.3.90-0.20030710.41rh)
Copyright 2003 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db
library "/lib/tls/libthread_db.so.1".
(gdb)
一旦gdb加载二进制文件,它就会显示一个提示,并等待命令。要调试所遇到的问题,首先要判断一下问题可能发生的地方。因为PrintAndExit()是负责将输出打印到屏幕上的,所以应以此为突破口。可以先设一个断点:
引用
(gdb)b PrintAndExit
Breakpoint 1 at 0x8048f2e: file hellogtk+.c, line 14.
当程序运行到断点时,要一步步执行程序,一次执行一行,试图发现问题所在。要开始执行应用程序,可以键入下面的命令:
引用
(gdb)run
Starting program: /mnt/linux5/mywork/hellogtk/hellogtk+
到这程序将停住,你可以在文本编辑区键入字符串“hello gdb”,然后按下print按钮。之后,hellogtk+会停止执行。返回到运行gdb的控制台。这时可以看到gdb的输出结果:
引用
Breakpoint 1, PrintAndExit (widget=0x9fde8f0, window=0x9fe6cb0)
at hellogtk+.c:14
14 gtk_entry_get_text(GTK_ENTRY(entry));
然后再一步一步的执行程:
引用
(gdb)n
15 if (str != (char *) NULL)
(gdb)n
16 printf("%s\n", str);
这时,程序执行到了print语句,所以print语句应是正确的,而值得怀疑的是str参数的值。该参数应是“hello gdb”。首先使用“print”判断字符串的值和它所指向的值:
引用
(gdb)print str
$1 = 0x9fe2b44 "\230'㘎t鑌a\001"
很显然,str指向的值很奇怪,可能是str指向了错误的地址,所以我们再来看一下源代码中的str的赋值情况:
引用
001 void
002 PrintAndExit (GtkWidget *widget, GtkWidget *window)
003 {
004 char *str;
005
006 gtk_entry_get_text(GTK_ENTRY(entry));
007 if (str != (char *) NULL)
008 printf("%s\n", str);
009
010 gtk_widget_destroy(window);
011 gtk_main_quit ();
012 }
可以看到,在第004行声明了str,第007和008行使用了它,但却一直没有给它赋值!gtkentry.h中的gtk_entry_get_text()原型如下所示:
引用
gchar *
gtk_entry_get_text(GtkEntry *entry);
要修改代码,需要将gtk_entry_get_text()返回的值赋给变量str。因此现在退出调试器,打开文本编辑器,将第006行修改如下:
引用
006 str = gtk_entry_get_text(GTK_ENTRY(entry));
重新编译和执行hellogtk+,会发现上述修改已经解决了bug。
当然这个bug似乎用不到gdb,这只是为了说明一下gdb的使用方法。gdb的功能不仅是这些,有关gdb更多的使用方法,可以参考我主页下载部分关于gdb的下载。
七、参考资料
引用
GTK+程序设计(C语言版) Syd Logan 著 战晓苏 王宁 等译 清华大学出版社
实用技术:开发Linux应用程序
──用GTK+和GDK开发Linux图形用户界面应用
[美]Eric Harlow 著 童寿彬 童悦 冯艺 等译 电子工业出版社
GTK+ FAQ http://www.gtk.org/faq
八、后记
文档写的很粗略,希望对你有用。如果你有什么建议或看法,可以给我回信,这里将表示感谢!