




已閱讀5頁,還剩8頁未讀, 繼續(xù)免費閱讀
版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
Jni中C+和Java的參數(shù)傳遞 Java Native Interface(JNI)是Java語言的本地編程接口,是J2SDK的一部分。在java程序中,我們可以通過JNI實現(xiàn)一些用java語言不便實現(xiàn)的功能。通常有以下幾種情況我們需要使用JNI來實現(xiàn)。1.標準的java類庫沒有提供你的應用程序所需要的功能,通常這些功能是平臺相關的。2.你希望使用一些已經(jīng)有的類庫或者應用程序,而他們并非用java語言編寫的。3.程序的某些部分對速度要求比較苛刻,你選擇用匯編或者c語言來實現(xiàn)并在java語言中調(diào)用他們。在java核心技術中,作者提到JNI的時候,建議不到萬不得已不要使用JNI技術,一方面它需要你掌握更多的知識才可以駕馭,一方面使用了JNI你的程序就會喪失可移植性。在本文我們跳過JNI的底層機制,讀者最好先把它想象為本地代碼和java代碼的粘合劑。利用VC+6.0實現(xiàn)JNI的最簡單的例子最近項目中設計到JNI的技術,對于VC+我是一知半解.JNI是知道和Native方法的接口,從來沒用過.但是摸了一會,還是感覺有點門路,搞定了JNI的難題以后,對于自己這點小小的進步不敢隱瞞,公開出來給還不了解的兄弟們作個參考. 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文件名稱可以隨便定.只要做好的動態(tài)鏈接庫改名成這個字符串就可以了.而native函數(shù)的來源就是該動態(tài)鏈接庫.2.做好該步準備以后,用javacTestNative.java生成.class.檢驗語法. 3.語法檢查通過以后,用javahTestNative生成.h的C頭文件. 4.打開VC+6.0,新建-;工程-;win32Dynamic-LinkLibrary.在向?qū)е羞x擇空工程. 5.把剛才javah生成的那個頭文件加入工程.然后文件-;新建-;textiles自己做一個.c文件.實現(xiàn)自己的native函數(shù).清單如下: #includes; JNIEXPORTjintJNICALLJava_TestNative_add(JNIEnv*ev,jobjectobj, jintx,jinty) Returnx+y; 備注: A其中的jni.h通常在jdkinclude可以先拷貝到VC安裝目錄下的include目錄下.一勞永逸,以后可以方便使用JNI技術. B全部的數(shù)據(jù)類型需要考慮Java和VC的接口問題.用jintjstring等. C函數(shù)名稱和自動生成的.h文件中規(guī)定的一致.命名規(guī)則是:Java_使用類_方法名 6全編譯一下工程. 如果沒有出錯,則此時生成動態(tài)鏈接庫成功.把動態(tài)鏈接庫拷貝到TestNative.java所在的目錄上. 7運行javaTestNative看結果吧.在實際的使用過程中,往往需要對參數(shù)進行處理轉(zhuǎn)換。才可以被C/C+程序識別。比如我們在C+中有一個結構(Struct)DiskInfo ,需要傳遞一個類似于DiskInfo *pDiskInfo的參數(shù),類似于在C+這樣參數(shù)如何傳遞到Java中呢?下面我們就來討論C+到Java中方法的一些常見參數(shù)的轉(zhuǎn)換:定義Native Java類:如果你習慣了使用JNI,你就不會覺得它難了。既然本地方法是由其他語言實現(xiàn)的,它們在Java中沒有函數(shù)體。但是,所有本地代碼必須用本地關鍵詞聲明,成為Java類的成員。假設我們在C+中有這么一個結構,它用來描述硬盤信息: / 硬盤信息 Struct Char name 256; Int serial; DiskInfo; 那么我們需要在Java中定義一個類來與之匹配,聲明可以寫成這樣: Class DiskInfo / 名字 Public String name; / 序列號 Public int serial; 在這個類中,申明一些Native的本地方法,來測試方法參數(shù)的傳遞,分別定義了一些函數(shù),用來傳遞結構或者結構數(shù)組,具體定義如下面代碼: /*/ /* * 定義本地方法 * */ / 輸入常用的數(shù)值類型(Boolean,Byte,Char,Short,Int,Float,Double) Public native void displayParms (String showText, int i, Boolean bl); / 調(diào)用一個靜態(tài)方法 Public native int add (int a, int b); / 輸入一個數(shù)組 Public native void set Array (Boolean blList); / 返回一個字符串數(shù)組 Public native String getStringArray (); / 返回一個結構 Public native DiskInfo getStruct (); / 返回一個結構數(shù)組 Public native DiskInfo getStructArray (); 編譯生成C/C+頭文件 定義好了Java類之后,接下來就要寫本地代碼。本地方法符號提供一個滿足約定的頭文件,使用Java工具Javah可以很容易地創(chuàng)建它而不用手動去創(chuàng)建。你對Java的class文件使用javah命令,就會為你生成一個對應的C/C+頭文件。1、在控制臺下進入工作路徑,本工程路徑為:E:workjavaworkspaceJavaJni。2、運行javah 命令:Javah -classpath E:workjavaworkspaceJavaJni Com.sundy.jnidemo. ChangeMethodFromJni本文生成的C/C+頭文件名為: com_sundy_jnidemo_ChangeMethodFromJni.h 在C/C+中實現(xiàn)本地方法生成C/C+頭文件之后,你就需要寫頭文件對應的本地方法。注意:所有的本地方法的第一個參數(shù)都是指向JNIEnv結構的。這個結構是用來調(diào)用JNI函數(shù)的。第二個參數(shù)jclass的意義,要看方法是不是靜態(tài)的(static)或者實例(Instance)的。前者,jclass代表一個類對象的引用,而后者是被調(diào)用的方法所屬對象的引用。 返回值和參數(shù)類型根據(jù)等價約定映射到本地C/C+類型,如表JNI類型映射所示。有些類型,在本地代碼中可直接使用,而其他類型只有通過JNI調(diào)用操作。使用數(shù)組JNI通過JNIEnv提供的操作Java數(shù)組的功能。它提供了兩個函數(shù):一個是操作java的簡單型數(shù)組的,另一個是操作對象類型數(shù)組的。因為速度的原因,簡單類型的數(shù)組作為指向本地類型的指針暴露給本地代碼。因此,它們能作為常規(guī)的數(shù)組存取。這個指針是指向?qū)嶋H的Java數(shù)組或者Java數(shù)組的拷貝的指針。另外,數(shù)組的布置保證匹配本地類型。為了存取Java簡單類型的數(shù)組,你就要要使用GetXXXArrayElements函數(shù)(見表B),XXX代表了數(shù)組的類型。這個函數(shù)把Java數(shù)組看成參數(shù),返回一個指向?qū)谋镜仡愋偷臄?shù)組的指針。當你對數(shù)組的存取完成后,要確保調(diào)用相應的ReleaseXXXArrayElements函數(shù),參數(shù)是對應Java數(shù)組和GetXXXArrayElements返回的指針。如果必要的話,這個釋放函數(shù)會復制你做的任何變化(這樣它們就反射到java數(shù)組),然后釋放所有相關的資源。為了使用java對象的數(shù)組,你必須使用GetObjectArrayElement函數(shù)和SetObjectArrayElement函數(shù),分別去get,set數(shù)組的元素。GetArrayLength函數(shù)會返回數(shù)組的長度。使用對象JNI提供的另外一個功能是在本地代碼中使用Java對象。通過使用合適的JNI函數(shù),你可以創(chuàng)建Java對象,get、set 靜態(tài)(static)和實例(instance)的域,調(diào)用靜態(tài)(static)和實例(instance)函數(shù)。JNI通過ID識別域和方法,一個域或方法的ID是任何處理域和方法的函數(shù)的必須參數(shù)。表C列出了用以得到靜態(tài)(static)和實例(instance)的域與方法的JNI函數(shù)。每個函數(shù)接受(作為參數(shù))域或方法的類,它們的名稱,符號和它們對應返回的jfieldID或jmethodID。如果你有了一個類的實例,它就可以通過方法GetObjectClass得到,或者如果你沒有這個類的實例,可以通過FindClass得到。符號是從域的類型或者方法的參數(shù),返回值得到字符串,如表D所示。下面我們來看看,如果通過使用數(shù)組和對象,從C+中的獲取到Java中的DiskInfo 類對象,并返回一個DiskInfo數(shù)組:/返回一個結構數(shù)組,返回一個硬盤信息的結構數(shù)組JNIEXPORT jobjectArray JNICALL Java_com_sundy_jnidemo_ChangeMethodFromJni_getStructArray (JNIEnv *env, jobject _obj) /申明一個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中對應的實例類中的變量*/ /獲取Java中的實例類 jclass objectClass = (env)-FindClass(com/sundy/jnidemo/DiskInfo); /獲取類中每一個變量的定義 /名字 jfieldID str = (env) -GetFieldID(objectClass,name,Ljava/lang/String;); /序列號 jfieldID ival = (env)-GetFieldID(objectClass,serial,I); /給每一個實例的變量付值,并且將實例作為一個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+方法實現(xiàn)代碼如下:/*/* 一縷陽光(sundy)版權所有,保留所有權利。*/*/* * TODO Jni 中一個從Java到C/C+參數(shù)傳遞測試類* author 劉正偉(sundy)* see /sundy* see mailto:* version 1.0* since 2005-4-30* * 修改記錄:* * 日期 修改人 描述* -*/ JniManage.cpp : 定義 DLL 應用程序的入口點。/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)用一個靜態(tài)方法,只有一個簡單類型輸出JNIEXPORT jint JNICALL Java_com_sundy_jnidemo_ChangeMethodFromJni_add(JNIEnv *env, jobject, jint a, jint b) int rtn = (int)(a + b); return (jint)rtn;/*/輸入一個數(shù)組,這里輸入的是一個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 );/*/返回一個字符串數(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;/返回一個結構,這里返回一個硬盤信息的簡單結構類型JNIEXPORT jobject JNICALL Java_com_sundy_jnidemo_ChangeMethodFromJni_getStruct(JNIEnv *env, jobject obj) /*/* 下面為獲取到Java中對應的實例類中的變量*/ /獲取Java中的實例類 jclass objectClass = (env)-FindClass(com/sundy/jnidemo/DiskInfo); /獲取類中每一個變量的定義 /名字 jfieldID str = (env)-GetFieldID(objectClass,name,Ljava/lang/String;); /序列號 jfieldID ival = (env)-GetFieldID(objectClass,serial,I); /給每一個實例的變量付值 (env)-SetObjectField(obj,str,(env)-NewStringUTF(my name is D:); (env)-SetShortField(obj,ival,10); return obj;/返回一個結構數(shù)組,返回一個硬盤信息的結構數(shù)組JNIEXPORT jobjectArray JNICALL Java_com_sundy_jnidemo_ChangeMethodFromJni_getStructArray(JNIEnv *env, jobject _obj) /申明一個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中對應的實例類中的變量*/ /獲取Java中的實例類 jclass objectClass = (env)-FindClass(com/sundy/jnidemo/DiskInfo); /獲取類中每一個變量的定義 /名字 jfieldID str = (env)-GetFieldID(objectClass,name,Ljava/lang/String;); /序列號 jfieldID ival = (env)-GetFieldID(objectClass,serial,I); /給每一個實例的變量付值,并且將實例作為一個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 測試native代碼這沒有什么多說的,看代碼吧/主測試程序 public static void main(String args) ChangeMet
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 藥品質(zhì)量投訴管理制度
- 藥品集中采購管理制度
- 藥店培訓考核管理制度
- 藥店甲類統(tǒng)籌管理制度
- 螢石公司環(huán)保管理制度
- 設備保養(yǎng)安全管理制度
- 設備啟用停用管理制度
- 設備建設公司管理制度
- 設備檢查檢測管理制度
- 設備私自拆卸管理制度
- 2025年 道路運輸企業(yè)主要負責人考試模擬試卷(100題)附答案
- 2025至2030中國執(zhí)法系統(tǒng)行業(yè)經(jīng)營效益及前景運行態(tài)勢分析報告
- 供應鏈公司展會策劃方案
- 南通市崇川區(qū)招聘 社區(qū)工作者筆試真題2024
- 全套桶裝飲用水(天然泉水、純凈水)QS體系文件(二)-程序文件
- 小數(shù)加減法脫式計算及簡便運算100道
- MSG-3中文版課件
- 盾構施工總結(doc106頁)
- 分部驗收橋梁主體驗收評估報告
- 計算機網(wǎng)絡設計畢業(yè)設計論文
- 關于郵政代理金融業(yè)務發(fā)展轉(zhuǎn)型的思考
評論
0/150
提交評論