1. 程式人生 > >Android系統下C語言hello world

Android系統下C語言hello world

在android上執行c編寫的helloword

  一般情況下Android系統應用程式都是java編寫APK,如果要重用C程式碼,也是通過JNI,呼叫C庫。
  也許有人會和我有一樣的想法既然android是基於linux的核心的,那應該也可以直接執行C編寫的二進位制呢?很顯然是可以的。
  當我們手機用USB線連線到電腦,電腦安裝adb工具,手機也允許電腦除錯就可以通過adb shell 進入android 。linux常用命令如:cd ls,也可以使用。這些程式就是android系統中C語言編寫的程式了 。

我們在linux下編寫一個hello.c如下:
#inlcude<stdio.h>

int main()
{
    printf("hello world \n");
    return 0;
}

 

在linux下通過gcc -o hello hello.c 編譯生成hello的可執行檔案,./hello打印出了hello world。

 

  我假想它在andorid 也能執行,adb push到到手機上,chmod 755 hello修改可執行許可權。執行./hello 出現了錯誤not executable: magic 7F45。原來我們編譯環境是x86編出來的二進位制只能在x86cpu上執行而android系統的是arm架構cpu的。所以我要編譯arm架構二進位制,編譯環境和執行環境不同的編譯,我們也叫做交叉編譯。
  廢了九牛二虎的力氣我下載arm的交叉編譯,結果沒有庫檔案 不能使用printf函式,編譯不通過。遇到問題解決唄,本來可以直接下載一個標準庫就行,為了方便我直接下載了一個arm-linux的交叉編譯工具。
  繼續gcc -o hello hell.c 生成了arm下二進位制檔案,一波操作傳輸到android 修改許可權,滿懷希望的 ./hello 結果大失所望No such file or directory 這又是什麼意思呢。百度一頓搜。
  原來是這樣啊。android下的c標準庫的 linux下使用的C標準庫和android下使用的庫不是一樣的。linux使用的glibc而在andorid下google沒有使用linux的glib自己實現了一個比glib更小
更快的bionic C標準庫,最重要的是android下linker連結器和linux的不一樣。linker主要是用來載入庫檔案到記憶體的。
  顯然我知道了原因了執行程式的時候到去找庫檔案的時候沒有找到就列印這句話。
  這裡有兩種解決辦法
  1.直接將hello程式靜態編譯arm二進位制讓他不依賴庫
     gcc -o hello helllo.c -static
   編譯完成後我們發現二進位制大了很多,printf函式編譯二進位制不再依賴庫函數了 在android下執行成功列印hello world 真是不容易終於成功了 。
 
2.使用andorid下庫和linker
下載android NDK 使用它來編譯 用這個編譯很多好處還可以使用android的日誌模組
  arm-linux-androideabi-gcc.exe -o hello  hell.c  –sysroot=”D:\NDK\platforms\android-19\arch-arm”
這樣編譯出來的二進位制能使用andorid C標準庫檔案大小也最合適 目前google推薦的也是這種方式。 
  
  程式釋出加上優化引數  在使用strip 來去掉除錯資訊減少二進位制大小。
  
  最後總結:雖然是個簡單的hello的hello world程式,但讓我加深了交叉編譯理解,瞭解作業系統載入庫的過程。