JAVA进阶day07JNI(java调用c)A部分
目前接觸的JNI有java調(diào)用c和c調(diào)用java兩類。其中java調(diào)用c又有隱式和顯示兩種映射關(guān)系。本筆記針對(duì)java調(diào)用c的顯示映射。本著工程實(shí)際夠用的原則,不夠再回頭來(lái)補(bǔ)充。 
 JAVA訪問(wèn)c庫(kù)需要有三個(gè)步驟 
 1:加載C庫(kù) 
 2:建立java函數(shù)名到c庫(kù)函數(shù)名的映射關(guān)系 
 3:在java程序里調(diào)用函數(shù) 
 先貼代碼,依照代碼來(lái)做分析:
分條縷析做筆記:
- 1:加載C庫(kù)和在java程序里調(diào)用函數(shù)
代碼中在靜態(tài)代碼塊中進(jìn)行加載c庫(kù)。可以知道我們要加載的是libnative.so庫(kù)。放到靜態(tài)代碼塊中可以保證該加載能夠只執(zhí)行一次。非常棒的處理。
public native void hello();native修飾的hello表明這個(gè)hello方法不是在java中實(shí)現(xiàn)的而是在本地語(yǔ)言中實(shí)現(xiàn)的。我們?cè)谑褂胔ello函數(shù)的時(shí)候首先要進(jìn)行聲明。這個(gè)聲明也可以聲明為靜態(tài)的,比如public native static void hello();這時(shí)候就沒(méi)有必要先實(shí)現(xiàn)JNIDemo的實(shí)例化靜態(tài)對(duì)象了,也就是說(shuō)我們可以省掉JNIDemo d=new JNI Demo();這個(gè)處理,直接使用JNIDemo.hello();當(dāng)然我們的main函數(shù)也是在JNIDemo類中的,可以直接寫為hello()。問(wèn)題又來(lái)了,那么同樣的道理為什么不是靜態(tài)的還需要實(shí)現(xiàn)JNIDemo對(duì)象呢,這個(gè)也是在JNIDemo的main函數(shù)中啊?這個(gè)就沒(méi)必要較真了,記住就好,又不是讓你去創(chuàng)造java語(yǔ)言,你只不過(guò)是用這個(gè)工具而已。我還發(fā)現(xiàn)這個(gè)public native static void hello()跟public static native void hello()是一個(gè)效果。無(wú)礙乎這個(gè)static跟native的前后。到此我們對(duì)這個(gè)加載c庫(kù)就算是掌握了。
- 2:建立java函數(shù)名到c庫(kù)函數(shù)名的映射關(guān)系 
 為了將java中的hello跟c語(yǔ)言中的函數(shù)對(duì)應(yīng)起來(lái),這部分的處理是c語(yǔ)言中做的。我們姑且猜測(cè),c語(yǔ)言在什么時(shí)候去做這個(gè)映射對(duì)應(yīng)呢?我提出一個(gè)想法,我們?cè)诩虞dSystemloadLibrary的時(shí)候會(huì)引起c庫(kù)文件中的一個(gè)觸發(fā),在那個(gè)觸發(fā)函數(shù)里面做了對(duì)應(yīng)。那么我們從文件中的結(jié)構(gòu)應(yīng)該是包含 觸發(fā) 實(shí)現(xiàn)。我們貼代碼分析:
我們看到,果不其然跟我們猜測(cè)的一模一樣。 
 的確是分為兩部分。最頂層那部分實(shí)現(xiàn)了c_hello函數(shù),最下半部分實(shí)現(xiàn)了一個(gè)JNI_OnLoad觸發(fā)函數(shù)。哇咔咔,一切都這么順滑。那我們開墾這個(gè)觸發(fā)函數(shù)吧。 
 該函數(shù)功能比較單一所以寫法肯定是固定的。每次使用我們只需要去修改這么幾個(gè)點(diǎn)就可以了: 
 JNI_VERSION_1_4 這個(gè)代表的是你使用的jni的版本。
這個(gè)作用就是從env找到JNIDemo這個(gè)類,方面后面我們?nèi)プ鲇成?。故而這個(gè)JNIDemo我們做移植的時(shí)候是需要去修改的。
if ((*env)->RegisterNatives(env, cls, methods, 1) < 0)這個(gè)地方也就是我們想要的注冊(cè)了。后面的1代表你要注冊(cè)的個(gè)數(shù)。 
 我們?cè)倏纯催@個(gè)注冊(cè)methods里面的實(shí)現(xiàn)。
這個(gè)模式也是固定的 
 其中“hello”對(duì)應(yīng)的是java中的函數(shù)名字。c_hello對(duì)應(yīng)的c文件中的函數(shù)名字。前面的void * 是永遠(yuǎn)不變的。中間的這個(gè)類型signature我是打死也不想記住怎么寫的。我們可以在寫完java文件之后使用javac JNIDemo.java進(jìn)行編譯然后使用 
 javah -jni JNIDemo 
 生成一個(gè)JNIDemo.h文件
我們從里面摘取
/** Class: JNIDemo* Method: hello* Signature: ()V*/就知道這個(gè)signature 就是()V. 
 同時(shí)我們知道我們的c文件的hello函數(shù)書寫形式應(yīng)該類似與
實(shí)際中我們的c語(yǔ)言函數(shù)書寫是
void c_hello(JNIEnv *env, jobject cls)幾乎是一樣的,其中jobject 跟jclass我覺(jué)得應(yīng)該是java編譯器不同導(dǎo)致的,我感性的認(rèn)為應(yīng)該是兼容的,都能用。既然我的編譯器出來(lái)的是jclass那么我的代碼就修改為
void c_hello(JNIEnv *env, jclass cls)寫到這里,還剩下兩件事,怎樣編譯c文件為lib*.so以及java同c語(yǔ)言文件如何傳遞返回?cái)?shù)據(jù)類型。我們知道java跟c的數(shù)據(jù)類型上是有區(qū)別的。包括開辟的空間大小等。最起碼的java中有string類型,然而我們的c語(yǔ)言中就沒(méi)有。因此,這部分還算是一個(gè)不大不小的知識(shí)點(diǎn)。按下不表下集再說(shuō)。
總結(jié)
以上是生活随笔為你收集整理的JAVA进阶day07JNI(java调用c)A部分的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
 
                            
                        - 上一篇: C语言完数求解
- 下一篇: 域用户权限|安装软件
