Android開發中在JAVA中呼叫C/C++ native程式碼
Android 從Java呼叫C/C++
當無法用 Java 語言編寫整個應用程式時,JNI 允許您呼叫C/C++本機程式碼。在下列典型情況下,您可能決定使用本機程式碼:
-
希望用更低階、更快的程式語言C/C++去實現對時間有嚴格要求的程式碼。
-
希望從 Java 程式訪問舊程式碼或程式碼庫。
-
需要標準 Java 類庫中不支援的依賴於平臺的特性。
我為什麼需要它?我的程式碼背景
我在安卓專案中,需要用到C++的soundtouch庫函式,因此必須將呼叫該庫的程式碼用C++編寫,然後再由java呼叫C++本機程式碼。
前提:已經配置好支援交叉呼叫的NDK(Native Development Kit,java與C/C++交叉呼叫的工具
問題及動機
網上有很多jni教程,但是對於安卓開發愛好者,如何在java程式碼中呼叫C/C++函式,實現我們想要的功能,卻沒有一個十分合適的教程,因此我寫下本文。
我要解決的問題:安卓前端有一個按鈕,點選該按鈕就可以實現“聲音特效處理”的功能。而這個功能的後臺實現的主要邏輯由C/C++程式碼編寫,因此需要從java呼叫C/C++程式碼。
須知:SWIG和javah的區別(強烈推薦)
我看了網上的關於 jni程式設計 的教程很多,但不盡相同,剛開始會犯迷糊。我想筆者往往忽略了一個關鍵點,那就是採用了什麼方式決定了步驟的流程。有兩種生成 jni的方式:一種是通過SWIG從C++程式碼生成過度的java程式碼;另一種是通過javah的方式從java程式碼自動生成過度的C++程式碼。兩種方式下的步驟流程正好相反
解決方案:從 Java 程式碼呼叫 C/C++ 的五個步驟
安卓開發中,從 Java 程式呼叫 C 或 C ++ 程式碼的過程由五個步驟組成。我們將在深入討論每個步驟,首先迅速地瀏覽一下,注意本文采用的方式是:SWIG 方式。
-
在jni資料夾下編寫C/C++程式碼,實現我們想要實現的C/C++邏輯。
-
根據C/C++程式碼,編寫 Java 程式碼。我們將根據寫好的C/C++函式,編寫 Java 類,這些類執行三個任務:宣告將要呼叫的native本機方法;裝入包含本機程式碼的共享庫;然後呼叫該本機方法。
-
首先用javah生成C/C++ 標頭檔案(.h 檔案),然後去改寫這個標頭檔案的方法,將我們自己的東西新增進去
-
寫一個Android.mk檔案,放在jni下的C/C++程式碼資料夾下
-
編譯執行 Java 程式。執行該程式碼,並檢視它是否有用。我們還將討論一些用於解決常見錯誤的技巧。
相關程式碼目錄結構(以我的程式碼結構為例)
src(放java程式碼)
|_ org.tecunhuman. jni 包(自定義命名的包)
|_ wrapperJNI.java (自己編寫的java程式碼,含native方法)
jni (放C/C++程式碼)
|_ soundstrech包(我的C++程式碼)
|_ gen包
|_ wrapper_wrap.cpp
|_ Android.mk
|_ RunParameters.cpp
|_ RunParameters.h
|_ SoundStrech.cpp
|_ SoundStrech.h
|_ WavFile.cpp
|_ WavFile.h
|_ wrapper.i
|_ soundtouch 包
——————————————————————————————
步驟 1:編寫C/C++程式碼(.cpp檔案)放在下jni下的C/C++程式碼資料夾
我們首先編寫一個.cpp檔案,
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
//SoundStrech.cpp程式碼
#include <stdexcept>
#include <stdio.h>
#include <string.h>
#include "RunParameters.h"
#include "WavFile.h"
#include "SoundTouch.h"
#include "BPMDetect.h"
#include "SoundStretch.h"
using namespace soundtouch;
|