NDK工具直接使用和分解使用

 轉載地址 

http://blog.csdn.net/rozenix/article/category/787011

 

I.NDK配置和基本使用

  下載解壓後即可使用。關鍵是不同版本的NDK開放的API不同,常用的是 r4和r5,後者面向Android 2.2+, 支持UI/圖形/聲音的部分C接口,還有STL的支持(遺憾的是r5中的STL沒整出來)。由於我面向的平臺是2.1的,所以,我用的是 r4c。

   那個NDK是真正配置好的完全支持C++(包括STL)的?網上比較有名的是Crystax NDK r4, 我用的是Mozilla 爲開發Android Firefox開發而使用的NDK r4c(與Crystax類似),下載地址是:

http://ftp.mozilla.org/pub/mozilla.org/mobile/source/android-ndk-r4c-0moz3.tar.bz2

具體如何修改自己的NDK我後面再說。

1.NDK的基本使用

   這裏說的基本使用,就是利用現有的NDK工具生成供SDK JAVA通過JNI調用的共享C庫(lib**.so)

   以工程Helloworld爲例,在工程文件夾下:

#mkdir jni

#cd jni

至少要創建Android.mk和helloworld.c,例如:

Android.mk

LOCAL_PATH := $(call my-dir)  

include $(CLEAR_VARS)    

LOCAL_MODULE := helloworld #庫名稱    

LOCAL_SRC_FILES := helloworld.c #源文件    

include $(BUILD_SHARED_LIBRARY) #生成共享庫    

 

這是個NDK要使用的小型Makefile,更多的選項可以看 $NDK/docs/* 內的相關文檔。

helloworld.c 遵從一般JNI代碼的規定:

#include <jni.h>   

jstring  Java_my_helloworld_Helloworld_hello( JNIEnv* env, jobject thiz )  

{  

  return (*env)->NewStringUTF(env, "Hello World from JNI !");  

}  

  注意C++代碼裏面要加上 extern "C",防止C++的名稱修飾使得JNI無法找到函數名。

 命名規則就是:Java_project_name_Activity_class_name_func_name.

  編譯生成,採用的是NDK封裝好的腳本ndk-build, 在$NDK主文件夾下,使用很簡單,在工程主文件夾

下執行:(假設$NDK已經加入到$PATH)

#ndk-build

...

即可,若成功,則主文件夾的 libs/armeabi 或者libs/arm-v7te 下生成 libhelloworld.so

2.SDK中使用NDK生成的文件

  修改src/my/helloworld/Helloworld.java,使之通過JNI調用C函數:


其中先加載libhelloworld.so,再調用其內的hellow()函數。

#ant debug

重建工程

 

前面提到的都是使用現有的ndk-build建立共享庫。如何建立可執行的C/C++文件?將jni/Android.mk內的

include $(BUILD_SHARED_LIBRARY) 改成include $(BUILD_EXECUTABLE) 即可。

那麼,想“自由使用”工具鏈,比如像使用gcc/g++那樣,尤其是想往Android上面移植 C/C++程序或者庫時,如何才能跳出ndk-build的限制?

  I.提取Android的gcc工具鏈

     如果你想偷懶的話,你很幸運,有現成的 ,附件的perl腳本agcc(csdn搞不出附件,只好鏈接新帖子) ,即可以完成工具鏈的抽取和封裝,可以像使用 gcc 那樣使用它,它最先來自

plausible.org/andy/agcc

    不過這個是面對整個Android開發包的(包括Android/SDK/NDK的所有文件),而且沒有C++/STL支持,我對它進行了修改,使它與上篇給出的ndk-r4配合,完全支持c/c++。

     如果你想自己動手,請這樣做:

1.分別對

1)生成可執行文件

2)靜態庫

3) 動態庫

4)多個源文件 的不同類型的工程使用

#ndk-build -B V=1

命令,會讓ndk-build “揭露出”整個工具鏈的不同使用過程 ,比如上篇中的helloworld工程:

顯示:

Compile thumb  : helloworld <= /opt/android/android-ndk-r4c/samples/helloworld/jni/helloworld.c
/opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/arm-eabi-gcc -I/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/include -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__  -Wno-psabi -march=armv5te -mtune=xscale -msoft-float -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64  -I/opt/android/android-ndk-r4c/samples/helloworld/jni -DANDROID  -Wa,--noexecstack -O2 -DNDEBUG -g  -c -MMD -MP -MF /opt/android/android-ndk-r4c/samples/helloworld/bin/ndk/local/armeabi/objs/helloworld/helloworld.o.d /opt/android/android-ndk-r4c/samples/helloworld/jni/helloworld.c -o /opt/android/android-ndk-r4c/samples/helloworld/bin/ndk/local/armeabi/objs/helloworld/helloworld.o
SharedLibrary  : libhelloworld.so
/opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/arm-eabi-gcc -nostdlib -Wl,-soname,libhelloworld.so -Wl,-shared,-Bsymbolic  /opt/android/android-ndk-r4c/samples/helloworld/bin/ndk/local/armeabi/objs/helloworld/helloworld.o -Wl,--whole-archive  -Wl,--no-whole-archive  /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/libgcc.a  /opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib/libc.so /opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib/libm.so    -Wl,--no-undefined -Wl,-z,noexecstack  -Wl,-rpath-link=/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/libgcc.a -o /opt/android/android-ndk-r4c/samples/helloworld/bin/ndk/local/armeabi/libhelloworld.so

......


從這些命令記錄分別提取出

1)工具的名稱和位置

例如gcc/g++工具是 arm-eabi-gcc/g++,位置是 /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/。。

2)工具相關選項和參數

交叉編譯時,最重要的就是編譯工具的相關參數設置,以及從環境中提取的文件(頭文件夾,鏈接文件,庫文件..)。下面的從上面提取的相關參數就不用我解釋了吧?(如果不熟悉這些的話,真的不應該直接從Android上手學交叉編譯,道理你們懂的。。)

CC = arm-eabi-gcc

CFLAGS/CXXFLAGS ="-fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums  -Wno-psabi -march=armv5te -mtune=xscale -msoft-float -mthumb -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64"

CPPFLAGS ="-I/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/include -fpic -mthumb-interwork -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -I/opt/android/android-ndk-r4c/samples/helloworld/jni -DANDROID "

CXX =arm-eabi-g++

LDFLAGS = "-nostdlib -Wl,-soname,libhelloworld.so -Wl,-shared,-Bsymbolic  -Wl,--whole-archive  -Wl,--no-whole-archive  /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/libgcc.a  /opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib/libc.so /opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib/libm.so    -Wl,--no-undefined -Wl,-z,noexecstack  -Wl,-rpath-link=/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/../../../../arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/bin/../lib/gcc/arm-eabi/4.4.0/libgcc.a"

3)工具的使用過程

  主要是面對不同的源文件(.c/.cpp/.o/.h...),以及不同的目標(生成什麼?.o/.exe/.s...),工具的使用過程和參數都是不同的,比如上例:

.c-->.o

$CC $CPPFLAGS $CFLAGS helloworld.c -c -g -o helloworld.o

僅僅 預處理-->編譯,未鏈接

然後

.o-->.so

$CC $LDFLAGS helloworld.o -o libhelloworld.so

完成鏈接

4)大家可以查看其他幾類情況,使用的工具和參數各不相同。


II.直接使用工具鏈

  提取出了工具鏈,弄清其不同參數和工作流程後,就可以自己指明使用了。首先將工具加入$PATH,然後,例如編譯如下的兩個全面測試C++功能的.cpp文件,要求ahoo.cpp -->libahoo.so(動態庫);a.cpp+libahoo.so --->a(程序):

ahoo.h


ahoo.cpp

a.cpp


命令就是:(都是先編譯,再鏈接,注意參數的區別)

1)ahoo.cpp--->ahoo.o a.cpp-->a.o

arm-eabi-g++ ahoo.cpp -I/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/include -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -DANDROID -DNDEBUG -mthumb-interwork -march=armv5te -mtune=xscale -msoft-float -mthumb -fpic -fPIC -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -Wno-psabi -Wa,--noexecstack -Os -O2 -c -o ahoo.o

 

arm-eabi-g++ a.cpp -I/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/include -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -DANDROID -DNDEBUG -mthumb-interwork -march=armv5te -mtune=xscale -msoft-float -mthumb -fpic -fPIC -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -Wno-psabi -Wa,--noexecstack -Os -O2 -c -o a.o


2) ahoo.o -->libahoo.so

arm-eabi-gcc ahoo.o -nostdlib -Wl,-shared,-Bsymbolic -Wl,--whole-archive -Wl,--no-whole-archive -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-rpath-link=/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -L/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -lc -lm /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/lib/gcc/arm-eabi/4.4.0/libgcc.a -o libahoo.so

 

3) a.o -->a

arm-eabi-gcc a.o -nostdlib -Bdynamic -Wl,-dynamic-linker,/system/bin/linker -Wl,--gc-sections -Wl,-z,nocopyreloc -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-rpath-link=/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -L/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -lc -lm /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/lib/gcc/arm-eabi/4.4.0/libgcc.a /opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib/crtend_android.o /opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib/crtbegin_dynamic.o -o a -lahoo -L./

  你是什麼感覺呢,不覺得太長太麻煩了嗎?何苦呢?何必呢?所以我纔將所有的內容都封裝在agcc 內的啊,你難道不想也這樣做嗎?(尤其是對程序或者庫進行 ./configure 的時候!),上面的例子,直接用我的agcc 的話(先將包含arm-eabi-*的路徑加入$PATH

#agcc ahoo.cpp -shared -o libahoo.so

Compile Thumb++    :ahoo.cpp    ===> ahoo.o

...

Link ARM shared lib    : ahoo.o     ====> libahoo.so

...

#agcc a.cpp -o a -lahoo -L./

Compile Thumb++    :a.cpp    ===> a.o

....

Link ARM executable    : a.o     ====> a

...

# file a
a: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), not stripped
#file libahoo.so
libahoo.so: ELF 32-bit LSB shared object, ARM, version 1 (SYSV), dynamically linked, not stripped

#arm-eabi-readelf -d a
Dynamic section at offset 0x132cc contains 23 entries:
  Tag        Type                         Name/Value
 0x00000001 (NEEDED)                     Shared library: [libc.so]
 0x00000001 (NEEDED)                     Shared library: [libm.so]
 0x00000001 (NEEDED)                     Shared library: [libahoo.so]
 0x00000020 (PREINIT_ARRAY)              0x1c2a4
 0x00000021 (PREINIT_ARRAYSZ)            0x8

.................

搞定!現在你也可以從自己的NDK出發提取組合自己的工具鏈了吧

 

Android中提取的工具鏈搭建好之後:

I.使用工具鏈移植c/c++程序或庫
  這類的程序的標準生成流程都是 :./configure -->make;make install 。想往Android上移植該怎麼辦?
1.(若需)修改代碼
  前面說到Android的C庫不是POSIX兼容的,很殘。若程序/庫需要Android沒有的內容或者不開放C接口的內容,那就悲劇了,你只有想法子改代碼了。比如想移植 alsa-lib,它使用了SYS V SHM(內存共享功能),這個Android沒有,有人質疑爲何沒有,Google官方回答:“Sorry!But NO!”這樣的話,只有設法在代碼內移除這個需求...
2.(若需)修改工程
  如果原工程沒有跨平臺支持的話,估計要修改configure,Makefile等文件才行。有兩種情況:
1)如zlib,在當前機器上直接./configure --prefix=/data/local,再修改生成的Makefile,將其中的CC=gcc RANLIB=ranlib LD=ld 改成 CC=agcc RANLIB=arm-eabi-ranlib LD=arm-eabi-ld ... 改完工具就可以直接make了。

2)如libffmpeg,還有另一條路(有時這是最後一條路 ):如果你夠強,直接利用Makefile.am(Makefile的來源文件)寫出工程的Android.mk文件,建立標準的NDK工程,利用ndk-build完成一切。(我討厭這招,因爲很費事,難成功)
3.直接上
  若你夠幸運,前面兩個都不需要的話(所以我非常喜歡freedesktop.org 提供的工程,非常規範全面),以下的一條命令就行了:
#CC=agcc CXX=agcc LD=arm-eabi-ld RANLIB=arm-eabi-ranlib /
PKG_CONFIG_LIBDIR=/data/local/lib/pkgconfig:/data/local/share/pkgconfig/ /
    ./configure /
    --prefix=/data/local /
    --host=arm-eabi-linux /
    --enable-malloc0returnsnull /
    --enable-shared

這裏有關鍵幾項,
1)CC=agcc 則常見的CFLAGS,CPPFLAGS,LDFLAGS等變量都不用提供了,都在agcc裏面。
2)PKG_CONFIG_LIBDIR ,當前的工程所需(若需)的庫文件的.pc(庫的描述文件)在哪個文件夾下面一定要指明,且不要用PKG_CONFIG_PATH, 後者會先找主機裏面的庫(比如主機的/usr/lib/之類的),再找目標環境裏的。
3)prefix, 目標環境的路徑。一般默認的是/usr/local或者/usr, 所以一定要改成目標環境的文件夾前綴,此處是 /data/local
4)host ,指的是目標平臺,也可以寫成 arm-unknown-linux等,不過一定要確認configure腳本能認識這個“型號”,不然會產生問題(拒絕生成動態庫等等)
5)--enable-shard, 不是所有的configure默認生成動態庫(我就碰到過,比如jpeg62),其他的選項類似。
6)還有,有的工程的configure方式 很特別(比如openssl和原版X11),但是大體都可以仿照以上解決。(關鍵是讓configure找到所需的工具鏈,找到所需的環境以及文件,並通過測試,成功生成Makefile)

接下來,除非編譯出錯(這就是上面兩個“若需”的工作),直接
#make;make install
就行了。


II.如何使用/運行編譯的成果?
1.基本使用
  收先你要有root權限,可以參考我寫的XT800 MOTO的刷機經歷 。相信大家注意到前面那個奇怪的prefix=/data/loc al 了,Android平臺上即使root用戶(開發者)也只是對設備的部分文件夾有權限修改,最常用的就是/data/local 和/data/bin了。而JAVA程序都在/data/data下,比如我們的Helloworld.apk安裝後

#adb shell ls /data/data/my.helloworld/lib/

-rw-r--r-- system   system      13225 2011-02-28 09:17 libhelloworld.so

可見它“自帶的”C庫也在裏面(如果有多個庫,只要確保 ant 最終生成之前將所有的.so放到libs/armeabi/下即可被打包進入.apk,java程序使用時別忘了所有自帶庫都要load一下)還有android裏面庫的標準路徑是/system/lib/,jni所用的自帶庫在/data/data/...裏面自己能找到,那麼C/C++程序呢?要放到允許放的地方去。比如我們上篇的 libahoo.so 和 a
#adb push libahoo.so /data/local/lib
#adb push a /data/local
#adb shell

進入android 設備的shell:
##ls

tmp
pds
cdrom
sqlite_stmt_journals
config
cache
sdcard
d
etc
system
sys
sbin
proc
init_prep_keypad_ttnm.sh
init.rc
init.mapphone_cg.rc
init.goldfish.rc
init
default.prop
data
root
dev

##ps

.....
system    1503  1169  122740 14612 ffffffff afe0d984 S com.motorola.process.system
app_33    1549  1169  121964 14556 ffffffff afe0d984 S com.android.alarmclock
app_51    1557  1169  121632 14024 ffffffff afe0d984 S com.motorola.firewall
app_54    1563  1169  121464 14260 ffffffff afe0d984 S com.motorola.extdisp
app_21    1611  1169  128052 15704 ffffffff afe0d984 S com.android.vending
app_32    1622  1169  123528 14428 ffffffff afe0d984 S com.motorola.apncontrol
app_3     1632  1169  133956 14700 ffffffff afe0d984 S com.hoho.campage
app_48    1648  1169  130216 15652 ffffffff afe0d984 S com.cooliris.media
app_81    1723  1169  123436 15032 ffffffff afe0d984 S com.moto.mobile.appstore
app_1     2507  1169  145004 26464 ffffffff afe0d984 S com.google.android.apps.maps
app_15    2559  1169  122940 16352 ffffffff afe0d984 S android.process.media
dhcp      2691  1     820    428   c00d4b28 afe0d7fc S /system/bin/dhcpcd
app_38    2738  1169  121404 14336 ffffffff afe0d984 S com.svox.pico
app_73    2745  1169  123112 15672 ffffffff afe0d984 S com.eshore.android
root      2770  1148  708    328   c006cb7c afe0d62c S /system/bin/sh
app_92    2776  1169  122612 17108 ffffffff afe0d984 S my.helloworld
root      2781  2770  860    344   00000000 afe0c75c R ps

##cat /proc/2776/maps

.....

80d00000-80d1d000 r-xp 00000000 1f:06 417        /system/lib/libmetainfo.so
80d1d000-80d1e000 rwxp 0001d000 1f:06 417        /system/lib/libmetainfo.so
80e00000-80e03000 r-xp 00000000 1f:08 1925     
  /data/data/my.helloworld/lib/libhelloworld.so
80e03000-80e04000 rwxp 00002000 1f:08 1925       /data/data/my.helloworld/lib/libhelloworld.so

80f00000-80f03000 r-xp 00000000 1f:06 275        /system/lib/hw/gralloc.omap3.so
80f03000-80f04000 rwxp 00003000 1f:06 275        /system/lib/hw/gralloc.omap3.so
....

##cd /data/local
##ls -l

-rwxrwxrwx shell    shell      458405 2011-02-28 13:04 a
-rwxrwxrwx shell    shell       76232 2009-07-31 19:08 su

drwxrwxrwx root     root       2010-12-08 19:14 mnt

drwxrwxrwx root     shell             2011-02-28 13:05 lib
drwxrwxrwx mot_tcmd shell             2011-03-01 13:04 tmp

##./a

link_image[1721]:  2786 could not load needed library 'libahoo.so' for './a' (load_library[1051]: Library 'libahoo.so' not found)CANNOT LINK EXECUTABLE
所以要把路徑加進去。
##LD_LIBRARY_PATH=/system/lib:/data/local/lib ./a

link_image[1721]:  2786 could not load needed library 'libahoo.so' for './a' (load_library[1051]: Library 'libahoo.so' not found)CANNOT LINK EXECUTABLE
??因爲要超級權限
##su
##LD_LIBRARY_PATH=/system/lib:/data/local/lib ./a

ahoooooooooo coming!
bagaaaaaaaaa coming!
bagaaaaaaaaa dying!
ahoooooooooo dying!
Horaaaaaaaaaaa
Woraaaaaaaaaaaa
sizeof hana:100
sizeof hana:100
libahoo.so:--exception.runtime_error.string:    --
libahoo.so:--exception.catch.string:    --You are Foooooooooyoooooooed!
a    :--string:   
這下總行了。


2.給SDK使用

  說實話,在Android設備上運行c程序,有何意義?最常用的還是移植c庫給java使用,比如下面這位的工作就很典型:

abitno.me/compile-ffmpeg -android -ndk

Android提供的解碼功能有限,他將ffmpeg庫移植到Android上成爲libffmpeg.so,開放JNI接口供上層JAVA UI使用,其結果就是一個新的Android播放器。而移植一個庫的過程如上所述兩類:編寫Android.mk 利用ndk-build創建libdep.so;或者使用agcc直接生成lib.so;然後再寫一個JNI接口層libinterface.so庫(除非你直接在原工程內寫好接口);放到Android工程的./libs/armeabi裏,最後在java內調用接口;要確保最終的.apk內包含所需的自帶庫。
  以下就是我寫的一個底層庫-->接口庫-->java的示例,可以參考:

#android create project -p ./ -t 4 -n Ahoo -k ore.ahoo -a Ahoo

#cat src/ore/ahoo/Ahoo.java

#cat res/values/styles.xml

(現在不清楚有什麼辦法讓單個Android.mk生成多個動態庫,大家可以試試)

#cat jni/dep.h

 

#cat jni/dep.cpp

#cat jni/ahoo.cpp

 

分別編譯(也可以用ndk-build):

#cd jni

#agcc dep.cpp -shared -o libdep.so -llog
Compile Thumb++    :dep.cpp    ===> dep.o
arm-eabi-g++ dep.cpp -I/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/include -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -DANDROID -DNDEBUG -mthumb-interwork -march=armv5te -mtune=xscale -msoft-float -mthumb -fpic -fPIC -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -Wno-psabi -Wa,--noexecstack -Os -O2 -c -o dep.o
Link ARM shared lib    : dep.o     ====> libdep.so
arm-eabi-gcc dep.o -nostdlib -Wl,-shared,-Bsymbolic -Wl,--whole-archive -Wl,--no-whole-archive -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-rpath-link=/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -L/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -lc -lm /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/lib/gcc/arm-eabi/4.4.0/libgcc.a -o libdep.so -llog

#agcc ahoo.cpp -shared -o libahoo.so -ldep -L./ -llog
Compile Thumb++    :ahoo.cpp    ===> ahoo.o
arm-eabi-g++ ahoo.cpp -I/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/include -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -DANDROID -DNDEBUG -mthumb-interwork -march=armv5te -mtune=xscale -msoft-float -mthumb -fpic -fPIC -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -Wno-psabi -Wa,--noexecstack -Os -O2 -c -o ahoo.o
Link ARM shared lib    : ahoo.o     ====> libahoo.so
arm-eabi-gcc ahoo.o -nostdlib -Wl,-shared,-Bsymbolic -Wl,--whole-archive -Wl,--no-whole-archive -Wl,--no-undefined -Wl,-z,noexecstack -Wl,-rpath-link=/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -L/opt/android/android-ndk-r4c/build/platforms/android-8/arch-arm/usr/lib -lc -lm /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libstdc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/arm-eabi/lib/libsupc++.a /opt/android/android-ndk-r4c/build/prebuilt/linux-x86/arm-eabi-4.4.0/lib/gcc/arm-eabi/4.4.0/libgcc.a -o libahoo.so -ldep -L./ -llog

#ls

ahoo.cpp  dep.cpp  dep.h  libahoo.so  libdep.so

#cd ..

#cp jni/lib* libs/armeabi/

#ant debug

........

BUILD SUCCESSFUL
Total time: 3 seconds

#adb install bin/Ahoo-debug.apk
1663 KB/s (188420 bytes in 0.110s)
    pkg: /data/local/tmp/Ahoo-debug.apk
Success

 

發佈了8 篇原創文章 · 獲贊 4 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章