01_JNI是什么,为什么使用,怎么用JNI,Cygwin环境变量配置,NDK案例(使用Java调用C代码),javah命令使用
1 什么是JNI
| JNI Java本地開發(fā)接口 |
| JNI是一個協(xié)議,這個協(xié)議用來溝通java代碼和外部的本地代碼(C/C++) 通過這個協(xié)議,java代碼就可以調(diào)用外部的C/C++代碼,外部的C/C++代碼也可以調(diào)用Java代碼。 |
2 為什么用JNI
| 1? JNI擴展了java虛擬機的能力,驅(qū)動開發(fā)(wifi-hotspot)2.3無線熱點共享 2? Native code效率高,數(shù)學運算,實時渲染的游戲上,音視頻處理(極品飛車),opengl,ffmpeg 3? 復用代碼(文件壓縮,人臉識別) 4? 特殊的業(yè)務場景 |
3 怎么用JNI
| 1 C/C++語言 2 掌握java ini流程 3 NDK(native develop kits) |
5 配置cygwin64的環(huán)境變量的方式是編寫\Cygwin\etc\profile,將ndk的路徑配置到path里面,截圖如下:
打開Cygwin輸入:Make –v,結(jié)果如下:
顯示出來GNI Make的版本,說明我們的cygwin模擬的Linux編輯環(huán)境模擬成功。
輸入ndk-build,出現(xiàn)以下結(jié)果:
顯示出上面的效果,說明環(huán)境變量已經(jīng)配置好了。
?
6 同樣可以將這個變量配置到windows下的環(huán)境變量中:配置如下:
進入CMD命令行窗口中,如果出現(xiàn)以下結(jié)果,說明配置成功:
?
當配置了第6步之后,若cygwin沒有配置成功時,也可以在window中的cmd命令行中使用ndk-build.
?
7 jni中的數(shù)據(jù)類型(后面是Java中的類型,左邊是C語言中的類型):
| #ifdef HAVE_INTTYPES_H # include <inttypes.h>????? /* C99 */ typedef uint8_t???????? jboolean;?????? /* unsigned 8 bits */ typedef int8_t????????? jbyte;????????? /* signed 8 bits */ typedef uint16_t??????? jchar;????????? /* unsigned 16 bits */ typedef int16_t???????? jshort;???????? /* signed 16 bits */ typedef int32_t???????? jint;???? ??????/* signed 32 bits */ typedef int64_t???????? jlong;????????? /* signed 64 bits */ typedef float?????????? jfloat;???????? /* 32-bit IEEE 754 */ typedef double???????? jdouble;??????? /* 64-bit IEEE 754 */ #else typedef unsigned char?? jboolean;????? ?/* unsigned 8 bits */ typedef signed char???? jbyte;????????? /* signed 8 bits */ typedef unsigned short? jchar;????????? /* unsigned 16 bits */ typedef short????????? jshort;???????? /* signed 16 bits */ typedef int??????????? jint;?????????? /* signed 32 bits */ typedef long long????? jlong;????????? /* signed 64 bits */ typedef float????????? jfloat;???????? /* 32-bit IEEE 754 */ typedef double??????? jdouble;??????? /* 64-bit IEEE 754 */ #endif ? /* "cardinal indices and sizes" */ typedef jint????????? ??jsize; |
8 案例效果(下面的土司是調(diào)用C語言代碼顯示的):
接下來編寫案例,使用java代碼調(diào)用C代碼,創(chuàng)建項目helloworldformc,代碼結(jié)構(gòu)如下:
其中libs下的內(nèi)容如下:
9 編寫MainActivity,代碼如下:
| package com.example.helloworldformc; ? import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.Toast; ? public class MainActivity extends Activity { ???????? // 1 定義一個c方法的接口?? 相當于在java代碼中定義了一個接口 ???????? //接口的實現(xiàn)方法是C語言實現(xiàn)的 ???????? public native String helloWorldFromC(); ?????????? ???????? // 5 步在java代碼中 引入庫函數(shù) ???????? static{ ?????????????????? System.loadLibrary("hello");// 注意事項 去掉前面的lib 后面的.so ???????? } ???????? ???????? @Override ???????? protected void onCreate(Bundle savedInstanceState) { ?????????????????? super.onCreate(savedInstanceState); ?????????????????? setContentView(R.layout.activity_main); ???????? } ???????? ???????? public void click(View view){ ?????????????????? // 彈出一個土司 土司的內(nèi)容 是c代碼寫出來 ?????? ?????????????????? // 第6步 ?????????????????? Toast.makeText(getApplicationContext(), helloWorldFromC(), 0).show(); ???????? } } |
10 在項目下創(chuàng)建一個jni目錄(這個是必須的),開始編寫Hello.c,代碼如下:
| #include <stdio.h> #include <jni.h> ? /* ?* 對應的是:public native String helloWorldFromC(){} ?* jstring:表示的是返回的是String類型的 ?* 函數(shù)名稱規(guī)則是:Java_包名_類名_方法名。 ?* ?* 注意:包名之間的"."在下面要變成下劃線 ?*/ jstring Java_com_example_helloworldformc_MainActivity_helloWorldFromC(JNIEnv* env,jobject obj) { ??? //2步? 實現(xiàn)C代碼 ??? //返回一個java String類型的字符串,使用一下函數(shù) ??? //jstring???? (*NewStringUTF)(JNIEnv*, const char*); ??? //(*env) 相當于 JNINativeInterface* JNIEnv ??? //*(*env)? 相當于 JNINativeInterface ? ??? //可以通過下面兩種方式返回參數(shù) ??? //return (**env).NewStringUTF(env,"helloworldfromc"); ? ??? return? (*env)->NewStringUTF(env,"helloworldfromc"); ? ??? //android.mk 告訴編譯器? 如何把C代碼打包成函數(shù)庫 ??? //3 生成.mk文件 ??? //4 步? 把C代碼? 打包成函數(shù)庫 } /*這里JNIEXPORT表示的是通過工具生成的,這時候也可以將JNIEXPORT去掉*/ JNIEXPORT jstring JNICALL Java_com_example_helloworldformc_MainActivity_hello_1world_1from_1c ?(JNIEnv * env, jobject obj){ } |
注意:上面的這個源文件的類名也可以通過javah命令生成,生成過程如下:
| (1)?????? 如果JDK使用的是1.6,使用javah命令前要到達:項目目錄\bin\classes目錄下
(2)?????? 如果JDK使用的是1.7,使用javah命令前要達到:項目目錄\bin\src目錄下: 例如(我使用的是JDK1.7):
在項目中生成.h:
|
11 Android.mk文件的內(nèi)容如下:
| #一個Android.mk文件必須下面這個變量開頭,它用于定位 #它用于定位你的源文件,my-dir這個宏是構(gòu)件系統(tǒng)提供的, #它用于返回當前目錄的路徑(這個目錄包含Android.mk它自己) LOCAL_PATH := $(call my-dir) ? #CLEAR_VARS也是build system構(gòu)件系統(tǒng)提供的,指定到一個指定的GNU Makefile文件 #這個Makefile文件幫你去清除一些LOCAL_XXX變量(比如:LOCAL_MODULE,LOCAL_SRC_FILES #,LOCAL_STATIC_LIBRARIES.等等...),除了LOCAL_PATH. include $(CLEAR_VARS) ? #LOCAL_MODULE變量必須在你的Android.mk文件中定義。名稱必須唯一 #并且不能包含一些空格,要注意的是構(gòu)件系統(tǒng)會自動的添加適當?shù)那熬Y和前綴 #換一句話說,一個命名為"foo"的共享庫模塊,會被生成"libfoo.so"文件。 #重要提示:如果你定義的模塊名稱是"libfoo",構(gòu)建系統(tǒng)將不會添加"lib"前綴, #并且也會生成"libfoo.so"文件。 LOCAL_MODULE??? := hello ? ? #LOCAL_SRC_FILES變量必須包含一個C或者C++的源文件集合,這些文件最終會被用于 #生成一個module,注意的是,這里不應該有頭文件和包含文件,因為構(gòu)件系統(tǒng)自動為您 #添加這些文件,只需要列出源文件就行了。 ? #注意:默認的C++源文件的后綴名是.cpp,同樣你也可以通過LOCAL_CPP_EXTENSION來自定義 #CPP的后綴名(例如:".cxx"可以,"cxx"不可以) LOCAL_SRC_FILES := Hello.c ? include $(BUILD_SHARED_LIBRARY) |
12 接下來使用cygwin,使用ndk-build來編譯程序
| (1)、如想將c變成.so的庫,需要使用ndk-build命令 (2)、將路徑路徑切換到工程目錄下。 (3)、然后執(zhí)行ndk-build這個操作(這個操作直接指定到項目路徑下就可以了)
注意:在使用這個ndk-build功能之前,需要有Android.mk文件(告訴編譯器,如何將C代碼打包成函數(shù)庫。具體的Android.mk怎么使用可以看ndk中的Android.html文檔) |
?
總結(jié)
以上是生活随笔為你收集整理的01_JNI是什么,为什么使用,怎么用JNI,Cygwin环境变量配置,NDK案例(使用Java调用C代码),javah命令使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一瓶可乐的热量有多大?
- 下一篇: 土鸡怎么样 了解土鸡的特点和饲养方法?