1. 程式人生 > >解決使用NDK進行編譯時出現undefined reference to function的問題

解決使用NDK進行編譯時出現undefined reference to function的問題

之前在編譯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的編譯似乎也有些許不同,需要多嘗試,多看前人經驗,儘量少踩坑,節省時間啊~