2011-03-30 77 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