2011-03-30 78 views
1

我使用最近的Glade开发了一个应用程序,所以我需要它在运行时使用GtkBuilder从XML加载UI。如果我尝试在具有太旧了一个GTK(如RHEL 5),它将无法像这样如何为不匹配的共享对象处理“未定义符号”错误

未定义的符号一个发行版上运行此:gtk_builder_new

这是正常的和预期。但是,我想知道是否有办法捕捉到这个错误,而是显示一个GUI错误对话框,例如“你的Gtk版本不够新”?这是我的main()开始之前发生的错误,所以问题是,有没有办法处理运行时链接错误?虽然使用谷歌搜索,我发现了一个链接器插件的概念,但我还没有找到有关的细节。这听起来像是我的应用程序之外必须存在的东西,所以也许这有点远。

我可以使用dlopen()加载Gtk,但这很荒谬,因为我必须给它的完整路径,然后我必须调用dlsym()很多来链接我需要的每个函数。 ld-linux.so搜索我。有没有一种方法可以使用ld-linux.so来告诉我libgtk的路径而不实际加载它,然后检查版本是否足够新(或只是否存在gtk_builder_new),然后在运行时链接完成,如果没有问题?

+0

使用'dlopen'和'dlsym'检查此特定功能 – Erik 2011-03-30 08:22:20

+0

感谢您提出的解决方案。最后我们停止了对RHEL 5的支持。我仍然认为一个非常理想的解决方案“捕捉链接错误并以任意,用户友好的方式显示它们”尚未实现,可能需要做一些关于如何完成运行时链接和启动流程的更根本性更改。 – ecloud 2011-08-23 17:32:27

回答

1

那么,它在Linux发行版上不会那样工作。你基本上做的是绕过包管理器。

好的方法是在目标发行版上构建你的软件。在配置时(调用./configure),您将看到不满足使用软件的要求。或者如果你没有配置脚本,编译器会在链接时叫喊。

然后,包装工的工作就是填写包装的要求。如果在你RPM包的.spec文件中,你需要gtk> = 2.16,那么在安装的时候,用户会看到一个对话框,告诉他一些依赖关系丢失了,他会看到他的GTK版本太旧了。

+0

是的,在软件包中需要更新的Gtk是一个好主意,但我问的是二进制文件是否可以在运行时处理链接错误。 – ecloud 2011-03-31 05:16:11

+0

你说得对,这是应该防止而不是解决的问题......如果用户不打算从软件包中获得任何用处,因为依赖关系没有得到满足,那么安装就没有意义了。 – ecloud 2011-08-23 17:34:21

0

这是一个解决方法,它可能有所帮助:重命名您的exe文件并创建一个调用它的bash脚本。

现在你可以这样做:

EXE=...name-of-your-real-executable... 
LOG=logfile 

$EXE > "$LOG" 2>&1 || { 
    if grep "undefined symbol: gtk_builder_new" "$LOG" ; then 
     ... show error message ... 
    fi 
} 

[编辑]或者,你可以创建一个非常小的测试程序,它只是包含调用gtk_builder_new和安装过程中或在测试脚本运行。

这样,您不需要检查特定的错误消息(可能会在非英语系统上翻译)。如果这个小测试程序失败了,你可以肯定这是因为这个缺少的符号,没有别的。

+0

是的,它似乎可以工作,我们只是不想有一个shell脚本。虽然有一个Gnome桌面文件,所以也许这对Gnome来说是一个很好的功能:在.desktop文件中有“需要gtk版本”元数据,并且可以在尝试启动之前进行检查。 – ecloud 2011-08-23 17:30:00

+0

在.desktop文件中有这样的元数据没有意义:桌面只是提供启动程序的方式;它不应该检查依赖关系。还有几个其他服务已经这样做(动态链接器,包管理软件)。那些工具有更多的信息,gtk只是你的exe需要的大概100个库中的一个。 – 2011-08-23 18:19:02

1

你似乎在谈论的情况是,你已经针对最近版本的头文件进行了编译,但是在你的库不够近的系统上运行。

GTK提供了一个工具,用于检查是否已链接到足够新的库的新版本。例如,如果你需要至少GTK 2.12(这是在GtkBuilder引入时的版本),你可以使用此代码甚至会显示一个漂亮的GUI错误对话框:

if (gtk_major_version < 2 || gtk_minor_version < 12) { 
    GtkWidget *dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, 
     GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, 
     "Your version of GTK is too old to run this program."); 
    gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), 
     "You need at least version 2.12.0; your version is %d.%d.%d.", 
     gtk_major_version, gtk_minor_version, gtk_micro_version); 
    gtk_dialog_run(GTK_DIALOG(dialog)); 
    gtk_widget_destroy(dialog); 
    exit(-1); 
} 
+0

这是正确的,但代码不会有机会运行,因为可执行文件有链接错误,所以main()永远不会启动。除非在“包装”可执行文件中使用此代码,在这种情况下,它就像shell脚本解决方案。 – ecloud 2011-08-23 17:27:23