Android native code的編譯和調試【轉http://billhoo.blog.51cto.com/2337751/1125039】

來源:互聯網
上載者:User
任。http://billhoo.blog.51cto.com/2337751/1125039

        光為這編譯及調試環境就前後折騰了兩三天,牆外找了很多教程,bill以為以下教程最為貼切

 

   Using eclipse for android - cc Development 

  Using eclipse for android - cc Dubugging 

        自己跟著教程一步一步做下去,期間也不乏出現懊惱的問題,雖煞費周折,但最終還是嘗到了編譯調試native code的甜頭。故模仿前文,以step-by-step方式記之,以備後用。----------------------------cut line------------------------------- 

 

  Step-0  環境準備        開發及編譯環境的下載和安裝工作,網上已連篇累牘,恕我不再贅述。以下僅列出本次教程所用到的環境及版本,用以核對。        1)普通的android開發環境(打算調試native code的朋友應該都已經具備這環境,我自己使                用的是Eclipse juno + ADT-ver: 21.0.1 + Android SDK + JDK6),本文使用的                eclipse經過了漢化,bill已經將links漢化包上傳,有需要的朋友可自行下載。        2)Cygwin 1.7.x                Cygwin的安裝需要注意開發包的下載,其預設為Default,我們需要自行選擇必要的開                發工具包,展開Devel節點                依次選擇如下工具包後,點擊下一步完成安裝。        3)android-ndk-r8d        4)Eclipse juno CDT外掛程式 - ver 8.1.1  Step-1  建立Android Demo工程        建立一個android工程NativeDebugDemo,使用android api 9(bill只在api-9和api-14上調試過,其它版本尚未涉足)。 

運行以確定基本的android環境能夠正常工作。

 

Step-2  建立並使用ndk-build編譯本項目的native code

        在Eclipse中右擊本項目名,建立檔案夾,命名為jni(大小寫敏感),在jni檔案夾中建立檔案,命名為Android.mk(大小寫敏感),繼續在jni目錄下建立檔案,命名為 demo.c

        在src目錄下建立包com.nativetools,並建立類NativeDemo(這個類僅僅為了將native code的聲明與普通android代碼聲明分離,以為下一篇文章中提到的代碼複用做準備)。

        編寫類代碼如下,對即將編寫的native code進行聲明(提示的警告可忽略):

  1. package com.nativetools; 
  2.  
  3. public class NativeDemo { 
  4.     static{ 
  5.         System.loadLibrary("DemoModule");  //載入native code的動態庫libDemoModule.so,稍後解釋 
  6.     } 
  7.      
  8.     public native int max(int a, int b);  //聲明函數max為native code,具體寫法請參照Oracle JNI doc 

        接下來需要編寫我們的本地代碼及Android.mk檔案,在demo.c中編寫用於本次Demo的本地C代碼如下,注意本地函數的命名結構:

                Java_

                com_nativetools_NativeDemo_

                max

        必須以“Java_”開頭,中間加上android中聲明該函數的類的限定名,此處就是之前的com.nativetools.NativeDemo(點號全部替換成底線,大小寫敏感),最後才是該函數的名稱“max”(關於本地代碼的函數命名及相關規範請參照Oracle JNI doc):

demo.c

  1. #include<jni.h> 
  2.  
  3. JNIEXPORT jint JNICALL 
  4. Java_com_nativetools_NativeDemo_max(JNIEnv *env, jobject jthis, jint a, jint b){ 
  5.     return a > b ? a : b; 

        接著,我們需要向android-ndk描述我們的本地代碼,編寫Android.mk如下

Android.mk

  1. LOCAL_PATH := $(call my-dir) 
  2.  
  3. include $(CLEAR_VARS) 
  4.  
  5. LOCAL_MODULE    := DemoModule 
  6. LOCAL_SRC_FILES := demo.c 
  7.  
  8. include $(BUILD_SHARED_LIBRARY) 

        關於Android.mk檔案的寫法請參照本地文檔/android-ndk-r8d/doc/ANDROID-MK.htlm

        代碼準備工作就緒,接下來需要配置Eclipse以完成本次Demo的編譯工作。

        首先,為了在Eclipse中編譯本地代碼,需要將當前android項目轉換成android + C/C++混合項目。右擊本項目名,建立→其它,選擇“Convert to C/C++ Project(Adds C/C++ Nature)”

        在接下來的對話方塊中選中本項目(預設已經選中),選擇“Convert to C Project”,在“Project type:”框中選擇“Makefile project”,在右邊“Toolchains”中選擇“--Other Toolchain”,點擊“完成”,彈出對話方塊詢問是否開啟C/C++透視圖,選擇“是”即可。

        現在開啟demo.c源檔案,可以看到CDT已經起了作用,demo.c中出現了很多無法識別的類型,接下來就需要進行C/C++相關的配置,引入必要的include路徑以解決這些問題。

        右擊項目名,選擇“屬性”,在彈出的屬性設定框中選擇“C/C++ Build”,在右邊“Builder Settings”中取消“Use Default build command”,並修改“Build command”路徑為你本機ndk-build.cmd程式的路徑,以bill自己的為例:“E:\Android_SDK\android-ndk-r8d\ndk-build.cmd”,點擊”應用“。

        切換到”Behaviour“選項卡,將”Build(Incremental build)“欄的”all“命令刪除,點擊”應用“。

        接著在左邊邊側欄選擇”C/C++ General“→”Paths and Symbols“,在右邊的”Includes“一欄選擇”GNU C“,點擊”Add“。

        點擊”File system...“,選擇android ndk對應平台(本項目是android api-9)的include路徑(裡面除了arch-arm以外還有兩個平台,這裡不用,詳情請參考android-ndk doc),以bill本機為例:”E:\Android_SDK\android-ndk-r8d\platforms\android-9\arch-arm\usr\include“,點擊”確定“,確定並關閉設定對話方塊。

        回到demo.c,可以看到剛才無法識別的類型已經全部能夠被CDT識別。右擊項目名,點擊”構建項目“,到此完成android + 本地C/C++的編譯過程。

        可以看到,編譯成功後,在項目/libs/armeabi/目錄下產生了動態連結程式庫”libDemoModule.so“,名稱”DemoModule“是bill在Androd.mk中指定的(首碼”lib“以及尾碼”.so“是ndk-build自行添加的,如果你在Android.mk中將模型名寫成”libDemoModule“,那麼ndk-build將不會再添加首碼”lib“,詳情請參見android-ndk doc)而在類NativeDemo中載入的庫正是”DemoModule“。

 

Step-3  在android中調用native code

        前面已經完成了native code的編譯工作,接下來我們需要在android中調用native code以驗證其正確與否。

        為簡單起見,bill直接在MainActivity的onCreate方法中進行實驗。修改onCreate方法如下:

  1. ... 
  2. import com.nativetools.NativeDemo; 
  3.  
  4. public class MainActivity extends Activity { 
  5.  
  6.     @Override 
  7.     protected void onCreate(Bundle savedInstanceState) { 
  8.         super.onCreate(savedInstanceState); 
  9.         setContentView(R.layout.activity_main); 
  10.  
  11.         NativeDemo nativetools = new NativeDemo(); 
  12.         Integer maxNum = nativetools.max(0, 1);  //調用本地函數 max 
  13.         new AlertDialog.Builder(this).setMessage(maxNum.toString()).show(); 
  14.     } 
  15. ... 

        完成後運行程式,可以看到快顯視窗中顯示數字”1“,我們的native code已經成功運行。

 

Step-4  native code的調試

        作為一個開發人員,bill認為調試所佔用的時間遠遠超過了單純的開發用時。如本文所述,我們在Step-3“開發”了一個調用native code的android實驗程式,但只要是程式就有bug,調試是必不可少的階段,下面bill就怎麼在eclipse上對native code進行調試加以闡釋,仿照前人的做法,分兩個部分展開。

        一者,用eclipse調試java代碼,並結合ndk-gdb以命令列的方式調試native code。

        一者,將二者合二為一,統一使用eclipse進行圖形化調試(這種方法使得調試變得直觀,但效能很糟糕)。

Step-4-1  eclipse + ndk-gdb調試native code

        首先我們需要將本項目設定為”可調試“。開啟”AndroidManifest.xml“,設定”Debuggable“為”true“。

        然後在eclipse中給java代碼打好斷點,為簡單起見,bill把斷點打在native code:max的入口處,啟動本項目的調試,待步進指標停止在斷點處。

        開啟Cygwin終端,cd進入本項目的根目錄,執行android-ndk-r8d根目錄下的ndk-gdb指令碼,為了查看啟動過程,加入verbose選項,即輸入命令”$ndk/ndk-gdb --verbose“(此處的”$ndk“是系統內容變數,指向android-ndk-r8d的根目錄,請自行配置),啟動如下:

        可以看到一個warning,警告有48個lib未能找到,其中包括”libstdc++.so“等,NDK官方文檔裡告訴大家:請直接忽略本警告~(bill當時花了大力氣想解決這個問題,無果,直到參看NDK doc......)

        到這裡就是大家所熟悉的”(gdb)“了,我們可以list出源碼,並在第5行打上斷點,然後continue,等待android端進入native code並觸發斷點。

        接著,eclipse端單步跳過-F6(或者單步跳入-F5),這時ndk-gdb這邊的斷點被觸發,我們可以進行日常的調試工作:

        調試完成後continue,流程回到eclipse,整個實驗性調試過程便可結束。

 

Step-4-2  使用eclipse統一調試native code

        不得不說,現階段性價比最高的調試方式就是eclipse + ndk-gdb了,雖然java與native code的調試分居兩地,但不論從效能還是配置的簡潔程度,都優於接下來要說的統一調試。對於這個統一調試法,bill也是學習了前人的配置,折騰半天才弄出來,所以希望以清晰的文字做個記錄。

        首先,複製android-ndk-r8d根目錄下的”ndk-gdb“指令碼到新檔案”ndk-gdb-eclipse“,將最後一行“$GDBCLIENT -x `native_path $GDBSETUP`”注釋掉或者直接刪除(最好別用記事本開啟,bill直接用的VS - -+),

        然後進入本項目的”\obj\local\armeabi“目錄,複製”gdb.setup“到新檔案”gdb2.setup“,開啟”gdb2.setup“並將”target remote :5039“這一句刪除,儲存退出。

        現在該目錄下應該有如下檔案,其中”app_progress“、”gdb2.setup“是一會需要用到的,如果缺少其中任意一個,請在Cygwin中,於本項目根目錄下運行一次”$ndk/ndk-gdb“即可。

        準備工作就緒,現在回到eclipse,點擊”調試“按鈕旁的下拉式箭頭,選擇”調試配置“,雙擊”C/C++ Application“,在右邊的”main“選項卡中點擊下方的”選擇其他“。

        進入後勾選”覆蓋工作空間設定“,並選擇”Standard Create Progress啟動程式“。

        確定退出,接著在C/C++ Application一欄填寫上面提到的app_progress的絕對路徑,bill本機設定如下:

        點擊”應用“,然後切換到”Debugger“標籤,在下方的”Debugger“欄中選擇”gdbserver“,勾選”stop on startup at:“並填寫我們的native函數名”Java_com_nativetools_NativeDemo_max“(也可以不勾選,在調試時打斷點即可)

        接著在”GDB debugger“一欄選擇對應的ndk-gdb版本,在bill本機為”E:\Android_SDK\android-ndk-r8d\toolchains\arm-linux-androideabi-4.6\prebuilt\windows\bin\arm-linux-androideabi-gdb.exe“,然後在”GDB command file:“一欄選擇我們前面提到的”gdb2.setup“,接著勾選下面的兩個選項,以達到在eclipse的控制台中與gdb進行互動的目的。

        點擊”應用“並切換到”connection“標籤,選擇”Type“為TCP,”Port number“為5039,儲存退出。

        一切準備工作就緒了,下面就開始在eclipse中進行統一的調試。注意各調試選項的啟動步驟,否則容易出現java斷點不命中,或者native code無法調試的現象。 

        首先,老樣子,在java代碼裡打上斷點,啟動普通調試選項,等待步進指標停止在斷點處。

        接著在Cygwin中,於本項目根目錄執行”ndk-gdb-eclipse“指令碼,即命令”$ndk/ndk-gdb-eclipse --verbose“,執行成功後不會進入gdb介面,稍後我們將在eclipse中見到(gdb)。

        待啟動完成後,回到eclipse,點擊調試按鈕旁的下拉式箭頭,選擇我們上面配置的那個C/C++調試配置,如果沒有,點擊”調試配置“,在裡面選擇上面配置好的那個,點擊”調試“。

        等待啟動完成後,我們會看到一個錯誤:

        不用管它,這是由於前文說的那個warning造成的,忽略掉即可。這時我們便能在eclipse的控制台中看到(gdb)了,你可以就在這裡和eclipse進行互動,或者直接使用可視化調試,進入demo.c源檔案,在需要斷點的地方雙擊,即可看到斷點資訊被同步到ndk-gdb中,然後同樣在eclipse單步跳入或者跳過,即可進入native code進行日常調試。

 -----------------cut line------------------------

Summary

        本次開發環境的下載、安裝及配置總耗時約4天,現在想來,其實也蠻簡單,但作為新手的自己,才開始配置的時候的確遇到了諸多困擾,幸得網上各位博主所寫文章的啟迪和協助,才成功搭建平台。因此,技術部落格的普及性及重要性可見一斑。

        bill希望自己也能在今後的開發生涯中不斷地積累經驗,不斷地用清晰的文字和邏輯記錄和分享自己所學所得,這也是作為一個博主最基本的使命吧。

Next

        下一篇文章bill將簡單介紹如何在另一個android應用中使用我們本文編譯產生的“libNativeDemo.so”動態連結程式庫。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.