近幾年,國內開源越鬧越火,不僅軟件開源,硬件也開源。去開源中國看看,已經有專門的硬件開源專區,61ic代碼工廠提供了許多的硬件(ARM、DSP等)相關的代碼。在這種趨勢下,從頭開始寫一個軟件或算法已經是上個世紀的事了,我們多多少少會從開源代碼中借鑒點經驗,甚至好的算法或中間件都會直接拿來用,當然,工程需要付費的就需要掏money了,不過提供開源免費代碼的網站卻還真不少,最有名的有sourceforge,github。我常常從github上下載別人的代碼,盡管github中的代碼良莠不齊,但長尾理論的告訴我們:除了Linux這種牛逼排名靠前的優秀源代碼外,那些star較低的Repositories中也有許多好的可供我們學習甚至可以直接在工程中使用的代碼,但需要我們去發現。
哎喲,扯遠了,回到正題……因為我們現在有太多可用的代碼,我們不用從頭編寫,而要做的大部分工作都是移植(更專業點的叫重構),這裡將持續地將自己移植工程(主要是C/C++工程)中遇到的問題及解決過程記錄下來,“掘地三尺非一日之功”,這是一個積累的過程。
1. 出現大量的 link error #10056: symbol "_fann_set_scaling_params" redefined
【情況】
在鏈接一個神經網絡的C語言庫fann時,出現大量的類似上面redefined錯誤,錯誤原因很明顯,“_fann_set_scaling_params重復定義”,而我在工程裡找遍了,發先確實都只在一處有定義。
【解釋】
_fann_set_scaling_params是編譯後.obj文件中的標識符號(symbol,一般這些符號開頭帶下劃線),以上錯誤出現在鏈接的時候,這說明多個.obj文件中出現了_fann_set_scaling_params的定義。我們知道,C編譯器是根據.c文件編譯的(即一個.c文件生成一個.obj,c編譯器不會主動去編譯頭文件)。而fann庫有所不同,其中一個floatfann.c文件中有這樣幾行代碼:
[cpp]
#include "fann.c"
#include "fann_io.c"
#include "fann_train.c"
#include "fann_train_data.c"
#include "fann_error.c"
#include "fann_cascade.c"
#include "fann.c"
#include "fann_io.c"
#include "fann_train.c"
#include "fann_train_data.c"
#include "fann_error.c"
#include "fann_cascade.c"你沒看錯,c語言中也是可以包含.c文件的,包含的.c文件會當做共成文件也編譯成.obj文件。這就明白了,我將上面包含的幾個.c文件添加到了工程裡面,而這裡又包含了這幾個.c文件,同一個.c文件編譯了兩次,當然會出現重復定義了。
【解決辦法】
第一種方法,將上面使用include包含的.c文件從工程中移除,第二種方法,將上面的#include "**.c"注釋掉,相應的源文件添加到工程中。
注:這是第一個問題,記得之前遇到過很多次類似的問題,每次都迷迷糊糊的弄了好久才解決,甚至程序編譯通過後還迷迷糊糊不知道怎麼就跑通了,真後悔沒早作記錄。這次在往DSP上移植fann時又遇到這個問題,謹記。
2. fatal error #5: could not open source file "fann.h"
【解釋】
相對於上面的編譯錯誤,這是鏈接錯誤,意思是說fann.h頭文件打不開,要麼壓根就沒有這個頭文件(檢查下頭文件名有沒有錯誤),要麼就是頭文件路徑設置不對(編譯器找到不頭文件)。
【解決方法】
在確定有這個頭文件的情況下,eclipse C/C++中解決問題的方法是,工程右鍵->Properities->Build->Compiler->Include Options,在-I選項中添加頭文件所在目錄。關於這一點,用過Linux下gcc編譯器的就會對頭文件搜索路徑,庫搜索路徑這些內容特別敏感,因此,這裡強烈推薦做軟件(尤其是C/C++軟件)的要學會gcc的使用,這對學會構建工程非常有用。