




已閱讀5頁,還剩8頁未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
Jni中C+和Java的參數(shù)傳遞 Java Native Interface(JNI)是Java語言的本地編程接口,是J2SDK的一部分。在java程序中,我們可以通過JNI實(shí)現(xiàn)一些用java語言不便實(shí)現(xiàn)的功能。通常有以下幾種情況我們需要使用JNI來實(shí)現(xiàn)。1.標(biāo)準(zhǔn)的java類庫沒有提供你的應(yīng)用程序所需要的功能,通常這些功能是平臺(tái)相關(guān)的。2.你希望使用一些已經(jīng)有的類庫或者應(yīng)用程序,而他們并非用java語言編寫的。3.程序的某些部分對(duì)速度要求比較苛刻,你選擇用匯編或者c語言來實(shí)現(xiàn)并在java語言中調(diào)用他們。在java核心技術(shù)中,作者提到JNI的時(shí)候,建議不到萬不得已不要使用JNI技術(shù),一方面它需要你掌握更多的知識(shí)才可以駕馭,一方面使用了JNI你的程序就會(huì)喪失可移植性。在本文我們跳過JNI的底層機(jī)制,讀者最好先把它想象為本地代碼和java代碼的粘合劑。利用VC+6.0實(shí)現(xiàn)JNI的最簡單的例子最近項(xiàng)目中設(shè)計(jì)到JNI的技術(shù),對(duì)于VC+我是一知半解.JNI是知道和Native方法的接口,從來沒用過.但是摸了一會(huì),還是感覺有點(diǎn)門路,搞定了JNI的難題以后,對(duì)于自己這點(diǎn)小小的進(jìn)步不敢隱瞞,公開出來給還不了解的兄弟們作個(gè)參考. Java中使用JNI調(diào)用DLL 1編寫范例文檔 PublicclassTestNative Privatenativeintadd(intx, inty); Publicstaticvoidmain (String args) TestNativehh=newTestNative (); intr=hh.add(30,20); System.out.println (result=+r); Static System.loadLibrary (DLL_0305); 其中LoadLibrary中的DLL文件名稱可以隨便定.只要做好的動(dòng)態(tài)鏈接庫改名成這個(gè)字符串就可以了.而native函數(shù)的來源就是該動(dòng)態(tài)鏈接庫.2.做好該步準(zhǔn)備以后,用javacTestNative.java生成.class.檢驗(yàn)語法. 3.語法檢查通過以后,用javahTestNative生成.h的C頭文件. 4.打開VC+6.0,新建-;工程-;win32Dynamic-LinkLibrary.在向?qū)е羞x擇空工程. 5.把剛才javah生成的那個(gè)頭文件加入工程.然后文件-;新建-;textiles自己做一個(gè).c文件.實(shí)現(xiàn)自己的native函數(shù).清單如下: #includes; JNIEXPORTjintJNICALLJava_TestNative_add(JNIEnv*ev,jobjectobj, jintx,jinty) Returnx+y; 備注: A其中的jni.h通常在jdkinclude可以先拷貝到VC安裝目錄下的include目錄下.一勞永逸,以后可以方便使用JNI技術(shù). B全部的數(shù)據(jù)類型需要考慮Java和VC的接口問題.用jintjstring等. C函數(shù)名稱和自動(dòng)生成的.h文件中規(guī)定的一致.命名規(guī)則是:Java_使用類_方法名 6全編譯一下工程. 如果沒有出錯(cuò),則此時(shí)生成動(dòng)態(tài)鏈接庫成功.把動(dòng)態(tài)鏈接庫拷貝到TestNative.java所在的目錄上. 7運(yùn)行javaTestNative看結(jié)果吧.在實(shí)際的使用過程中,往往需要對(duì)參數(shù)進(jìn)行處理轉(zhuǎn)換。才可以被C/C+程序識(shí)別。比如我們?cè)贑+中有一個(gè)結(jié)構(gòu)(Struct)DiskInfo ,需要傳遞一個(gè)類似于DiskInfo *pDiskInfo的參數(shù),類似于在C+這樣參數(shù)如何傳遞到Java中呢?下面我們就來討論C+到Java中方法的一些常見參數(shù)的轉(zhuǎn)換:定義Native Java類:如果你習(xí)慣了使用JNI,你就不會(huì)覺得它難了。既然本地方法是由其他語言實(shí)現(xiàn)的,它們?cè)贘ava中沒有函數(shù)體。但是,所有本地代碼必須用本地關(guān)鍵詞聲明,成為Java類的成員。假設(shè)我們?cè)贑+中有這么一個(gè)結(jié)構(gòu),它用來描述硬盤信息: / 硬盤信息 Struct Char name 256; Int serial; DiskInfo; 那么我們需要在Java中定義一個(gè)類來與之匹配,聲明可以寫成這樣: Class DiskInfo / 名字 Public String name; / 序列號(hào) Public int serial; 在這個(gè)類中,申明一些Native的本地方法,來測(cè)試方法參數(shù)的傳遞,分別定義了一些函數(shù),用來傳遞結(jié)構(gòu)或者結(jié)構(gòu)數(shù)組,具體定義如下面代碼: /*/ /* * 定義本地方法 * */ / 輸入常用的數(shù)值類型(Boolean,Byte,Char,Short,Int,Float,Double) Public native void displayParms (String showText, int i, Boolean bl); / 調(diào)用一個(gè)靜態(tài)方法 Public native int add (int a, int b); / 輸入一個(gè)數(shù)組 Public native void set Array (Boolean blList); / 返回一個(gè)字符串?dāng)?shù)組 Public native String getStringArray (); / 返回一個(gè)結(jié)構(gòu) Public native DiskInfo getStruct (); / 返回一個(gè)結(jié)構(gòu)數(shù)組 Public native DiskInfo getStructArray (); 編譯生成C/C+頭文件 定義好了Java類之后,接下來就要寫本地代碼。本地方法符號(hào)提供一個(gè)滿足約定的頭文件,使用Java工具Javah可以很容易地創(chuàng)建它而不用手動(dòng)去創(chuàng)建。你對(duì)Java的class文件使用javah命令,就會(huì)為你生成一個(gè)對(duì)應(yīng)的C/C+頭文件。1、在控制臺(tái)下進(jìn)入工作路徑,本工程路徑為:E:workjavaworkspaceJavaJni。2、運(yùn)行javah 命令:Javah -classpath E:workjavaworkspaceJavaJni Com.sundy.jnidemo. ChangeMethodFromJni本文生成的C/C+頭文件名為: com_sundy_jnidemo_ChangeMethodFromJni.h 在C/C+中實(shí)現(xiàn)本地方法生成C/C+頭文件之后,你就需要寫頭文件對(duì)應(yīng)的本地方法。注意:所有的本地方法的第一個(gè)參數(shù)都是指向JNIEnv結(jié)構(gòu)的。這個(gè)結(jié)構(gòu)是用來調(diào)用JNI函數(shù)的。第二個(gè)參數(shù)jclass的意義,要看方法是不是靜態(tài)的(static)或者實(shí)例(Instance)的。前者,jclass代表一個(gè)類對(duì)象的引用,而后者是被調(diào)用的方法所屬對(duì)象的引用。 返回值和參數(shù)類型根據(jù)等價(jià)約定映射到本地C/C+類型,如表JNI類型映射所示。有些類型,在本地代碼中可直接使用,而其他類型只有通過JNI調(diào)用操作。使用數(shù)組JNI通過JNIEnv提供的操作Java數(shù)組的功能。它提供了兩個(gè)函數(shù):一個(gè)是操作java的簡單型數(shù)組的,另一個(gè)是操作對(duì)象類型數(shù)組的。因?yàn)樗俣鹊脑?,簡單類型的?shù)組作為指向本地類型的指針暴露給本地代碼。因此,它們能作為常規(guī)的數(shù)組存取。這個(gè)指針是指向?qū)嶋H的Java數(shù)組或者Java數(shù)組的拷貝的指針。另外,數(shù)組的布置保證匹配本地類型。為了存取Java簡單類型的數(shù)組,你就要要使用GetXXXArrayElements函數(shù)(見表B),XXX代表了數(shù)組的類型。這個(gè)函數(shù)把Java數(shù)組看成參數(shù),返回一個(gè)指向?qū)?yīng)的本地類型的數(shù)組的指針。當(dāng)你對(duì)數(shù)組的存取完成后,要確保調(diào)用相應(yīng)的ReleaseXXXArrayElements函數(shù),參數(shù)是對(duì)應(yīng)Java數(shù)組和GetXXXArrayElements返回的指針。如果必要的話,這個(gè)釋放函數(shù)會(huì)復(fù)制你做的任何變化(這樣它們就反射到j(luò)ava數(shù)組),然后釋放所有相關(guān)的資源。為了使用java對(duì)象的數(shù)組,你必須使用GetObjectArrayElement函數(shù)和SetObjectArrayElement函數(shù),分別去get,set數(shù)組的元素。GetArrayLength函數(shù)會(huì)返回?cái)?shù)組的長度。使用對(duì)象JNI提供的另外一個(gè)功能是在本地代碼中使用Java對(duì)象。通過使用合適的JNI函數(shù),你可以創(chuàng)建Java對(duì)象,get、set 靜態(tài)(static)和實(shí)例(instance)的域,調(diào)用靜態(tài)(static)和實(shí)例(instance)函數(shù)。JNI通過ID識(shí)別域和方法,一個(gè)域或方法的ID是任何處理域和方法的函數(shù)的必須參數(shù)。表C列出了用以得到靜態(tài)(static)和實(shí)例(instance)的域與方法的JNI函數(shù)。每個(gè)函數(shù)接受(作為參數(shù))域或方法的類,它們的名稱,符號(hào)和它們對(duì)應(yīng)返回的jfieldID或jmethodID。如果你有了一個(gè)類的實(shí)例,它就可以通過方法GetObjectClass得到,或者如果你沒有這個(gè)類的實(shí)例,可以通過FindClass得到。符號(hào)是從域的類型或者方法的參數(shù),返回值得到字符串,如表D所示。下面我們來看看,如果通過使用數(shù)組和對(duì)象,從C+中的獲取到Java中的DiskInfo 類對(duì)象,并返回一個(gè)DiskInfo數(shù)組:/返回一個(gè)結(jié)構(gòu)數(shù)組,返回一個(gè)硬盤信息的結(jié)構(gòu)數(shù)組JNIEXPORT jobjectArray JNICALL Java_com_sundy_jnidemo_ChangeMethodFromJni_getStructArray (JNIEnv *env, jobject _obj) /申明一個(gè)object數(shù)組 jobjectArray args = 0; /數(shù)組大小 jsize len = 5; /獲取object所屬類,一般為java/lang/Object就可以了 jclass objClass = (env)-FindClass(java/lang/Object); /新建object數(shù)組 args = (env) -NewObjectArray (len, objClass, 0); /* 下面為獲取到Java中對(duì)應(yīng)的實(shí)例類中的變量*/ /獲取Java中的實(shí)例類 jclass objectClass = (env)-FindClass(com/sundy/jnidemo/DiskInfo); /獲取類中每一個(gè)變量的定義 /名字 jfieldID str = (env) -GetFieldID(objectClass,name,Ljava/lang/String;); /序列號(hào) jfieldID ival = (env)-GetFieldID(objectClass,serial,I); /給每一個(gè)實(shí)例的變量付值,并且將實(shí)例作為一個(gè)object,添加到objcet數(shù)組中 for(int i=0; i SetObjectField(_obj,str,(env)-NewStringUTF(my name is D:); (env)-SetObjectField(_obj,str,jstr); (env)-SetShortField(_obj,ival,10); /添加到objcet數(shù)組中 (env)-SetObjectArrayElement(args, i, _obj); /返回object數(shù)組 return args; 全部的C/C+方法實(shí)現(xiàn)代碼如下:/*/* 一縷陽光(sundy)版權(quán)所有,保留所有權(quán)利。*/*/* * TODO Jni 中一個(gè)從Java到C/C+參數(shù)傳遞測(cè)試類* author 劉正偉(sundy)* see /sundy* see mailto:* version 1.0* since 2005-4-30* * 修改記錄:* * 日期 修改人 描述* -*/ JniManage.cpp : 定義 DLL 應(yīng)用程序的入口點(diǎn)。/package com.sundy.jnidemo;#include stdafx.h#include #include #include jni.h#include jni_md.h#include ./head/Base.h#include head/wmi.h#include head/com_sundy_jnidemo_ChangeMethodFromJni.h /通過javah jni javactransfer 生成#include #include stdlib.h#include string.h#pragma comment (lib,BaseInfo.lib)#pragma comment (lib,jvm.lib)/硬盤信息struct char name256; int serial;DiskInfo;/*/*BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) LPTSTR strName = new CHAR256 ; (*GetHostName)(strName); printf(%sn,strName); delete strName; return TRUE;*/將jstring類型轉(zhuǎn)換成windows類型char* jstringToWindows( JNIEnv *env, jstring jstr );/將windows類型轉(zhuǎn)換成jstring類型jstring WindowsTojstring( JNIEnv* env, char* str );/主函數(shù)BOOL WINAPI DllMain(HANDLE hHandle, DWORD dwReason, LPVOID lpReserved) return TRUE;/輸入常用的數(shù)值類型 Boolean,Byte,Char,Short,Int,Float,DoubleJNIEXPORT void JNICALL Java_com_sundy_jnidemo_ChangeMethodFromJni_displayParms(JNIEnv *env, jobject obj, jstring s, jint i, jboolean b) const char* szStr = (env)-GetStringUTFChars(s, 0 ); printf( String = %sn, szStr ); printf( int = %dn, i ); printf( boolean = %sn, (b=JNI_TRUE ? true : false) ); (env)-ReleaseStringUTFChars(s, szStr );/調(diào)用一個(gè)靜態(tài)方法,只有一個(gè)簡單類型輸出JNIEXPORT jint JNICALL Java_com_sundy_jnidemo_ChangeMethodFromJni_add(JNIEnv *env, jobject, jint a, jint b) int rtn = (int)(a + b); return (jint)rtn;/*/輸入一個(gè)數(shù)組,這里輸入的是一個(gè)Boolean類型的數(shù)組JNIEXPORT void JNICALL Java_com_sundy_jnidemo_ChangeMethodFromJni_setArray(JNIEnv *env, jobject, jbooleanArray ba) jboolean* pba = (env)-GetBooleanArrayElements(ba, 0 ); jsize len = (env)-GetArrayLength(ba); int i=0; / change even array elements for( i=0; i ReleaseBooleanArrayElements(ba, pba, 0 );/*/返回一個(gè)字符串?dāng)?shù)組JNIEXPORT jobjectArray JNICALL Java_com_sundy_jnidemo_ChangeMethodFromJni_getStringArray(JNIEnv *env, jobject) jstring str; jobjectArray args = 0; jsize len = 5; char* sa = Hello, world!, JNI, is, fun ; int i=0; args = (env)-NewObjectArray(len,(env)-FindClass(java/lang/String),0); for( i=0; i NewStringUTF(sai ); (env)-SetObjectArrayElement(args, i, str); return args;/返回一個(gè)結(jié)構(gòu),這里返回一個(gè)硬盤信息的簡單結(jié)構(gòu)類型JNIEXPORT jobject JNICALL Java_com_sundy_jnidemo_ChangeMethodFromJni_getStruct(JNIEnv *env, jobject obj) /*/* 下面為獲取到Java中對(duì)應(yīng)的實(shí)例類中的變量*/ /獲取Java中的實(shí)例類 jclass objectClass = (env)-FindClass(com/sundy/jnidemo/DiskInfo); /獲取類中每一個(gè)變量的定義 /名字 jfieldID str = (env)-GetFieldID(objectClass,name,Ljava/lang/String;); /序列號(hào) jfieldID ival = (env)-GetFieldID(objectClass,serial,I); /給每一個(gè)實(shí)例的變量付值 (env)-SetObjectField(obj,str,(env)-NewStringUTF(my name is D:); (env)-SetShortField(obj,ival,10); return obj;/返回一個(gè)結(jié)構(gòu)數(shù)組,返回一個(gè)硬盤信息的結(jié)構(gòu)數(shù)組JNIEXPORT jobjectArray JNICALL Java_com_sundy_jnidemo_ChangeMethodFromJni_getStructArray(JNIEnv *env, jobject _obj) /申明一個(gè)object數(shù)組 jobjectArray args = 0; /數(shù)組大小 jsize len = 5; /獲取object所屬類,一般為ava/lang/Object就可以了 jclass objClass = (env)-FindClass(java/lang/Object); /新建object數(shù)組 args = (env)-NewObjectArray(len, objClass, 0); /*/* 下面為獲取到Java中對(duì)應(yīng)的實(shí)例類中的變量*/ /獲取Java中的實(shí)例類 jclass objectClass = (env)-FindClass(com/sundy/jnidemo/DiskInfo); /獲取類中每一個(gè)變量的定義 /名字 jfieldID str = (env)-GetFieldID(objectClass,name,Ljava/lang/String;); /序列號(hào) jfieldID ival = (env)-GetFieldID(objectClass,serial,I); /給每一個(gè)實(shí)例的變量付值,并且將實(shí)例作為一個(gè)object,添加到objcet數(shù)組中 for(int i=0; i SetObjectField(_obj,str,(env)-NewStringUTF(my name is D:); (env)-SetObjectField(_obj,str,jstr); (env)-SetShortField(_obj,ival,10); /添加到objcet數(shù)組中 (env)-SetObjectArrayElement(args, i, _obj); /返回object數(shù)組 return args; /將jstring類型轉(zhuǎn)換成windows類型char* jstringToWindows( JNIEnv *env, jstring jstr ) int length = (env)-GetStringLength(jstr ); const jchar* jcstr = (env)-GetStringChars(jstr, 0 ); char* rtn = (char*)malloc( length*2+1 ); int size = 0; size = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL ); if( size ReleaseStringChars(jstr, jcstr ); rtnsize = 0; return rtn;/將windows類型轉(zhuǎn)換成jstring類型jstring WindowsTojstring( JNIEnv* env, char* str ) jstring rtn = 0; int slen = strlen(str); unsigned short * buffer = 0; if( slen = 0 ) rtn = (env)-NewStringUTF(str ); else int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 ); buffer = (unsigned short *)malloc( length*2 + 1 ); if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) 0 ) rtn = (env)-NewString( (jchar*)buffer, length ); if( buffer ) free( buffer ); return rtn;Java 測(cè)試native代碼這沒有什么多說的,看代碼吧/主測(cè)試程序 public static void main(String args) ChangeMet
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年經(jīng)濟(jì)法考試復(fù)習(xí)資料試題及答案
- 高校生職業(yè)規(guī)劃精英戰(zhàn)
- 2025游戲開發(fā)合同范本
- 2025年經(jīng)濟(jì)法特征試題及答案揭秘
- 經(jīng)濟(jì)師綜合素質(zhì)的提升中級(jí)經(jīng)濟(jì)師試題及答案
- 水利水電工程有關(guān)法規(guī)知識(shí)試題及答案
- 2025年經(jīng)濟(jì)法復(fù)習(xí)必看題目
- 2025年工程項(xiàng)目管理行業(yè)現(xiàn)狀試題及答案
- 英語教學(xué)課件Unit 4 單詞課件人教版八下Unit 4 Why dont you talk to your
- 水電工程數(shù)據(jù)處理試題及答案
- 新課標(biāo)(水平三)體育與健康《籃球》大單元教學(xué)計(jì)劃及配套教案(18課時(shí))
- DL∕T 5210.6-2019 電力建設(shè)施工質(zhì)量驗(yàn)收規(guī)程 第6部分:調(diào)整試驗(yàn)
- 2023版毛概課后答案
- 大貓英語分級(jí)閱讀 二級(jí)2 Let's go shopping 課件
- 《中國文化概論》課程教學(xué)大綱.docx
- 化妝品注冊(cè)注銷申請(qǐng)表
- 建筑物及構(gòu)筑物拆除質(zhì)量控制措施
- 自密實(shí)混凝土的設(shè)計(jì)與實(shí)踐-C30自密實(shí)混凝土配合比設(shè)計(jì)
- BF——2008——0603 北京市房屋租賃合同
- 張緊輪支架加工工藝及夾具設(shè)計(jì)說明書
- 晨間戶外區(qū)域混齡體育活動(dòng)的組織與實(shí)施ppt課件
評(píng)論
0/150
提交評(píng)論