2014-06-24 30 views
1

我正在使用靜態庫,它使用printf()生成std輸出。我如何攔截它,以便在我的應用程序中顯示輸出結果並進行突出顯示?如何在C++代碼中攔截printf()?

我有lib的來源,我可以稍微修改它,如果需要。

+0

這裏有類似的問題的答案:http://stackoverflow.com/questions/5911147/how-to-redirect-printf-output-back-into-code and here: http://stackoverflow.com/questions/1599109/redirecting -printf 兩者都建議使用管道來捕獲stdout輸出,並設置單獨的線程/進程來攔截它。這些答案可能值得一看。 – quercus32

回答

2

我的lib的來源,如果需要,我可以稍微修改它。

好吧,如果你真的相信他們正在使用printf,你可以建立自己的代碼,你可以使用對他們,只要你沒有在那裏等場所使用printf

(我假設一個類Unix平臺上,所以有可能需要做一些修改,以得到這個工作在其他地方。)

一兩件事你可以做的是重新定義printf指向你自己的版本。另一種方法是編寫自己的printf並將其鏈接到標準庫之前。這兩條路線都不是你認爲推薦的做法,儘管它們應該可行。這兩條路線都不需要修改圖書館的來源。

重新定義的printf

在這裏,我們只是告訴它,它真是一個不同功能的printf編譯器的概念混亂。加入這樣的事情你的Makefile:

CFLAGS += -Dprintf=redirected_printf 
CXXFLAGS += -Dprintf=redirected_printf 

(有些編譯系統使用變量DEFINES爲了這個目的,因人而異。)

這告訴編譯器與redirected_printf更換標識printf的每個實例。這與您將#define printf redirected_printf置於每個源文件的頂部相同。

現在你只需要編寫redirected_printf函數。我傾向於將格式化傳遞給stdio中的另一個函數vasprintf,它與printf執行相同的操作,但它需要va_list而不是...,並返回一個指向具有輸出的堆分配字符串的指針。

#include <stdarg.h> 
#include <stdio.h> 
extern "C" int redirected_printf(const char * format, ...) { 
    // Make formatted string. 
    char* outstr = 0; 
    va_list ap; 
    va_start(ap, format); 
    int result = vasprintf(&outstr, format, ap); 
    va_end(ap); 
    if(result < 0) // Error occurred and `outstr` undefined if result < 0. 
     return result; 

    // Do something with the string in `outstr` here, like display it in a dialog. 

    // Clean up and return. 
    free(outstr); 
    return result; 
} 

更換的printf

這是有點麻煩,因爲你必須寫一個名爲printf功能上面就像replacement_printf,然後你要說服鏈接器,而不是鏈接到您的版本的標準庫的。您可能只需將您的printf粘貼到您的某個編譯單元中即可完成;當熟料鏈接您將重定向到您的源的庫時,它會找到您的printf並鏈接到它;那麼稍後當它看到標準庫中的一個時,它會放棄它,因爲那時沒有任何東西叫它。

如果這不起作用,可以嘗試使用arranlib命令將printf放入您自己的庫中,然後將該庫鏈接到您重定向的庫之後。

請注意,如果您嘗試重定向的庫是共享庫(如DLL或.so文件),則可能無法使用;它在製造時與標準printf相連。

這條路線有更多的警告,取決於你的鏈接器是如何工作的以及其他一些事情,所以我不推薦它,但爲了完整性我將它包括在內。