NDK系列文章(一)—— NDK概覽

JNI 簡介

  • 名稱:Java Native Interface 即Java本地接口
  • 作用:使得Java與本地其他類型語言(如C、C++)交互
  • JNI是Java調用Native語言的一種特性,JNI屬於Java的,與Android無直接關係
  • Java通過JNI可以調動由C/C++實現的驅動,從而擴展Java虛擬機

實現步驟:

  • 在java中聲明Native方法(即需要調用的本場方法)
  • 編譯上述Java源文件(javac得到.class文件)
  • 通過javap命令導出JNI的頭文件(.h文件)
  • 編譯.so庫文件
  • 通過Java命令執行Java程序,最終實現Java調用本地代碼

NDK 簡介

  • 名稱:Native Development Kit,是Android的一個工具開發包
  • 作用:快速開發C、C++的動態庫,並自動將so和應用一起打包成APK
  • 在Android的場景下使用JNI,提供了把.so和.apk打包的工具
  • NDK提供的庫有限,僅擁有算法效率和敏感的問題
  • 提供了交叉編譯器。用於生成特定的CPU平臺動態庫

NDK和JNI的關係

JNI是實現Java調用C/C++的途徑,NDK是Android中實現JNI的手段,即在Android中通過NDK從而實現JNI的功能!

常用C/C++編譯器

  • clang:是一個C、C++、Object-C的輕量級編譯器。基於LLVM。
  • gcc:GNU C編譯器。原本只能處理C語言,現在可以處理C++
  • g++:GNU c++編譯器,後綴爲.c的源文件,gcc把它當作是C程序,而g++當作是C++程序;後綴爲.cpp的,兩者都會認爲是c++程序,g++會自動鏈接c++標準庫stl,gcc不會,gcc不會定義__cplusplus宏,而g++會
  • GDB:是一個由GNU開源組織發佈的、UNIX/Linux操作系統下的、基於命令行的、功能強大的程序調試工具

C/C++文件編譯過程

  • 預處理:該階段主要處理include和define等。它把#include包含進來的.h 文件插入到#include所在的位置,把源程序中使用到的用#define定義的宏用實際的字符串代替

  • 編譯:編譯階段,編譯器檢查代碼的規範性、語法錯誤等。檢查無誤後,編譯器把代碼翻譯成彙編語言

  • 彙編:彙編階段把 .s 文件翻譯成二進制機器指令文件 .o,這個階段接收.c、.i、.s的文件都沒問題

  • 鏈接:該階段鏈接的是其餘的函數庫,比如我們自己編寫的c/c++文件中用到了三方的函數庫,在連接階段就需要連接三方函數庫,如果連接不到就會報錯

以上四個階段可以用對應的命令處理查看:
1、預處理 gcc -E main.c -o main.i
2、編譯階段 gcc -S main.i -o main.s
3、彙編階段 gcc -c main.s -o main.o
4、鏈接階段 gcc main.o -o main.exe

靜態庫(static libaray .a)和動態鏈接庫(dynamic link library .so)

  • 靜態庫通常情況下,對函數的鏈接是放在編譯時期(compile time)完成的。所有相關的對象文件(object file)與牽涉到的函數庫(library)被鏈接合成一個可執行文件(executable file)。程序在運行時,與函數庫再無瓜葛,因爲所有需要的函數已拷貝到自己門下。所以這些函數庫被成爲靜態庫(static libaray),通常文件名爲“libxxx.a”的形式 Android可以使用靜態庫
  • 動態庫,對一些庫函數的鏈接載入推遲到程序運行的時期(runtime),可以實現進程之間的資源共享。將一些成語升級變得簡單,甚至可以真正做到鏈接載入完全由程序員在程序代碼中控制

交叉編譯

  • 本地編譯:在當前編譯平臺下,編譯出來的程序只能放到當前平臺下運行。

比如,我們在 x86 平臺上,編寫程序並編譯成可執行程序。這種方式下,我們使用 x86 平臺上的工具,開發針對 x86平臺本身的可執行程序,這個編譯過程稱爲本地編譯

  • 交叉編譯:在當前編譯平臺下,編譯出來的程序能運行在體系結構不同的另一種目標平臺上,但是編譯平臺本身卻不能運行該程序。

比如,我們在 x86 平臺上,編寫程序並編譯成能運行在 ARM 平臺的程序,編譯得到的程序在 x86 平臺上是不能運行的,必須放到 ARM 平臺上才能運行

交叉編譯器的命名規則:

我們在使用交叉編譯鏈時,常常會看到這樣的名字:arm-none-linux-gnueabi-gcc、arm-cortex_a8-linux-gnueabi-gcc、mips-malta-linux-gnu-gcc等。這些交叉編譯鏈的命名規則有一定的規則。
arch-core-kernel-system:
arch - - 用於哪個目標平臺;
core - - 使用哪個CPU Core, 如Cortex A8, 但也有一些命名比較靈活的,有以廠家或開發版本命名的,還有的直接是none或者cross;
kernel - - 所運行的OS,如Linux、uclinux、bare(無OS);
system - - 交叉編譯鏈所選擇的庫函數和目標映像的規範,如gun、guneabi等。其中gnu等價於glibc+oabi;gnueabi等價於glibc+eabi

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章