之前在編譯jni時出現了undefined reference to function這個問題,查閱相關資料說是可能鏈接的庫問題,然後通過各種gcc調整順序解決了這個問題。這個工程是導師的工程,工程在Linux環境下運行無誤,我從Linux環境往Android jni的一個遷移,由於文件的關聯比較多代碼量異常龐大和複雜(嘗試着把方法直接複製到目標cpp中無果),而且我對gcc編譯順序這方面不是特別熟悉,在更改了Android.mk中的源文件順序無果後,轉向源碼分析。
首先問題是出現在A.cpp中,其出錯信息如下:
jni/A.cpp:518: error: undefined reference to ‘func1’
jni/A.cpp:531: error: undefined reference to ‘func2’
jni/A.cpp:533: error: undefined reference to ‘func3’
其中func1是在頭文件B1.h中聲明的,func2、func3是在頭文件B2.h中聲明的。
接着分析下A.cpp中的關鍵頭文件包含信息:
//A.cpp
...
#include "A.h"
#include "X1.h"
#include "X2.h"
#include "X3.h"
...
然後是A.h中的頭文件包含信息:
//A.h
...
#include "B1.h"
#include "B2.h"
...
發現X1.h、X2.h、X3.h中均包含了B1.h、B2.h這兩個頭文件
大概框架是這樣的
A.cpp
- A.h
- B1.h
- B2.h
- X1.h
- B1.h
- B2.h
- X2.h
- B1.h
- B2.h
- X3.h
- B1.h
- B2.h
天知道他爲什麼能寫出這樣的代碼……
猜想:A.cpp是否需要再次包含B1和B2兩個頭文件呢?於是改成了如下形式:
//A.cpp
...
#include "A.h"
#include "X1.h"
#include "X2.h"
#include "X3.h"
#include "B1.h"
#include "B2.h"
...
//A.h
...
#include "B1.h"
#include "B2.h"
...
嘗試後發現依舊不行,於是再猜想:是否因爲X1.h、X2.h、X3.h包含了B1.h、B2.h導致B1.h和B2.h實際上並沒有包含進來呢?於是繼續修改:
//A.cpp
...
#include "A.h"
#include "B1.h"
#include "B2.h"
...
//A.h
...
#include "B1.h"
#include "B2.h"
...
結果依舊是錯誤,那麼又猜想,是否因爲A.h包含了B1.h、B2.h導致A.cpp實際上並沒有包含進這兩個頭文件呢,於是把A.h中的B1.h、B2.h刪掉,改變如下:
//A.cpp
...
#include "A.h"
#include "B1.h"
#include "B2.h"
...
//A.h
...
//B1.h/B2.h去掉
...
發現編譯居然沒有報這個錯了,但是報了其它函數缺失某個結構體的錯誤,這個結構體依賴於B1.h和B2.h,於是加上原來的X1.h、X2.h和X3.h,結構如下:
//A.cpp
...
#include "A.h"
#include "X1.h"
#include "X2.h"
#include "X3.h"
#include "B1.h"
#include "B2.h"
...
//A.h
...
//B1.h/B2.h去掉
...
發現編譯居然通過了!
於是再次猜想:編譯可能跟頭文件的包含順序有關,如果A.cpp先包含B1.h和B2.h這兩個頭文件是否能夠獲取到這兩個頭文件的func1、func2和func3呢?於是再作修改:
//A.cpp
...
#include "B1.h"
#include "B2.h"
#include "A.h"
#include "X1.h"
#include "X2.h"
#include "X3.h"
//#include "B1.h"
//#include "B2.h"
...
//A.h
...
#include "B1.h"
#include "B2.h"
...
居然還是編譯成功了!
PS:C++菜鳥,對這個基本上不懂,只能一點點去嘗試摸索。嵌套包含是個坑,Linux的編譯和NDK的編譯似乎也有些許不同,需要多嘗試,多看前人經驗,儘量少踩坑,節省時間啊~