這文章寫的不錯(cuò),
JNI(java Native Interface)是Java語(yǔ)言的一部分,可以訪問(wèn)非Java語(yǔ)言編寫的程序,也可以用于在C++程序中執(zhí)行Java代碼。
步驟:
1> 編寫帶有native聲明方法的Java類,并且該方法只定義不實(shí)現(xiàn),后期由c++負(fù)責(zé)實(shí)現(xiàn):
// HelloCpp.java
public class HelloCpp
{
// ...
public native void callCpp();
// ...
}
2> 由于后期的C++實(shí)現(xiàn)代碼最終會(huì)被編譯為一個(gè)動(dòng)態(tài)庫(kù).dll,因此需要在Java類中定義一個(gè)靜態(tài)代碼塊,提前加載該動(dòng)態(tài)庫(kù),假設(shè)動(dòng)態(tài)的名字為hellocpp.dll:
// HelloCpp.java
public class HelloCpp
{
static
{
System.loadLibrary("hellocpp");
}
public native void callCpp();
// ...
}
3> 在Java類中定義main方法調(diào)用該native方法:
// HelloCpp.java
public class HelloCpp
{
static
{
System.loadLibrary("hellocpp");
}
public native void callCpp();
public static void main(String[] args)
{
System.out.PRintln("***** JNI Test *****");
HelloCpp instance = new HelloCpp();
instance.callCpp(); // 調(diào)用native方法
}
}
4> 編譯包含native方法的Java類,生成class字節(jié)碼文件:
javac HelloCpp.java // 生成HelloCpp.class
5> 生成與native方法對(duì)應(yīng)的.h頭文件:
javah –jni HelloCpp // 生成HelloCpp類對(duì)于的頭文件HelloCpp.h
// HelloCpp.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloCpp */
#ifndef _Included_HelloCpp
#define _Included_HelloCpp
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloCpp
* Method: callCpp
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_HelloCpp_callCpp(JNIEnv* env, jobject this);
#ifdef __cplusplus
}
#endif
#endif
6> 使用C++實(shí)現(xiàn)native方法:
// HelloCpp.cpp
#include "HelloCpp.h"
#include <jni.h>
#include <iostream>
JNIEXPORT void JNICALL Java_HelloCpp_callCpp(JNIEnv* env, jobject this)
{
std::cout << "C++ Implementation" << std::endl;
}
7> 編譯生成動(dòng)態(tài)庫(kù)hellocpp.dll:
g++ -Wl,--kill-at –shared –I D:/jdk1.7.0_75/include –I D:/jdk1.7.0_75/include/win32 HelloCpp.cpp –o hellocpp.dll
8> 調(diào)用hellocpp.dll來(lái)運(yùn)行Java程序:
Java HelloCpp
結(jié)果如下:
***** JNI Test *****
C++ Implementation
說(shuō)明:
JNIEXPORT void JNICALL Java_HelloCpp_callCpp(JNIEnv* env, jobject this);
JNIEXPORT和JNICALL是宏。
JNIEnv*指向一個(gè)位置,該位置包含一個(gè)指向函數(shù)表的指針,表中的每一項(xiàng)都是一個(gè)指向JNI函數(shù)的指針,native方法通過(guò)JNI函數(shù)訪問(wèn)JVM的中的數(shù)據(jù) ,如下所示:

第二個(gè)參數(shù)對(duì)于非靜態(tài)方法為jobject,對(duì)于靜態(tài)方法為jclass。jobject表示調(diào)用native方法對(duì)象自身的引用,如同C++中的this指針;jclass表示定義native方法的類的引用。
如下介紹帶有參數(shù)和返回值的native方法:
// Prompt.java

1 class Prompt 2 { 3 static 4 { 5 System.loadLibrary("Prompt"); 6 } 7 private native String GetLine(String prompt); 8 9 public static void main(String[] args)10 {11 Prompt p = new Prompt();12 String input = p.GetLine("Enter a line:");13 System.out.println("Your Input is: " + input);14 }15 }


// Prompt.h

1 /* DO NOT EDIT THIS FILE - it is machine generated */ 2 #include <jni.h> 3 /* Header for class Prompt */ 4 5 #ifndef _Included_Prompt 6 #define _Included_Prompt 7 #ifdef __cplusplus 8 extern "C" { 9 #endif10 /*11 * Class: Prompt12 * Method: GetLine13 * Signature: (Ljava/lang/String;)Ljava/lang/String;14 */15 JNIEXPORT jstring JNICALL Java_Prompt_GetLine(JNIEnv* env, jobject _this, jstring prompt);16 17 #ifdef __cplusplus18 }19 #endif20 #endif
// Prompt.cpp

1 #include "Prompt.h" 2 #include <iostream> 3 4 JNIEXPORT jstring JNICALL Java_Prompt_GetLine(JNIEnv* env, jobject _this, jstring prompt) 5 { 6 char buf[1024]; 7 const char* str; 8 str = env->GetStringUTFChars(prompt, NULL); /* 獲得傳入的字符串,將其轉(zhuǎn)換為native Strings */ 9 if(str == NULL) /* str == NULL意味著JVM為native String分配內(nèi)存失敗 */10 {11 return NULL;12 }13 std::cout << str; /* 顯示傳入的字符串參數(shù) prompt */ 14 env->ReleaseStringUTFChars(prompt, str); /* 通知JVM釋放String所占的內(nèi)存 */15 16 std::cin.get(buf, 1024);17 return env->NewStringUTF(buf); /* 構(gòu)造新的Java.lang.String,如果JVM分配內(nèi)存失敗,則拋出OutOfMemoryError,并且返回NULL */18 }
補(bǔ)充信息:
:: UTF-8字符串以’/0’結(jié)尾,而Unicode字符串則不是。如果需要獲得Unicode格式的jstring的長(zhǎng)度,可以使用GetStringLength;如果需要獲得UTF-8格式的jstring的長(zhǎng)度,可以先使用GetStringUTFChars,在其結(jié)果上使用strlen,或者直接使用GetStringUTFLength。
:: GetStringUTFChars的第二個(gè)參數(shù)為jboolean *isCopy,其指向分配的內(nèi)存空間,如果isCopy被設(shè)為JNI_TRUE,那么返回的String是Java String的一個(gè)副本;如果被設(shè)為JNI_FALSE,那么返回一個(gè)指向Java String本身的指針,此時(shí)不允許修改返回的String。
:: 函數(shù)對(duì)Get/ReleaseStringCritical的作用于Get/ReleaseStringChars類似,但是對(duì)于程序員而言,該函數(shù)對(duì)之間的代碼相當(dāng)于“臨界區(qū)”。在該“臨界區(qū)”內(nèi),native代碼不能調(diào)用任何的JNI函數(shù),否則將引起當(dāng)前線程阻塞。
:: GetStringRegion/GetStringUTFRegion將Unicode格式的String復(fù)制到預(yù)分配的緩沖區(qū)中,由于不需要JVM分配內(nèi)存,因此也就不需要釋放操作:
按 Ctrl+C 復(fù)制代碼JNIEXPORT jstring JNICALL Java_Prompt_GetLine(JNIEnv* env, jobject _this, jstring prompt){ char inbuf[1024], outbuf[1024]; int len = env->GetStringUTFLength(prompt); env->GetStringUTFRegion(prompt, 0, len, outbuf); std::cout << outbuf; std::cin.get(inbuf, 1024); return env->NewStringUTF(inbuf); }
總結(jié):
1> 數(shù)據(jù)類型對(duì)應(yīng)關(guān)系表:
Java 類型 | 本地 C 類型 | 實(shí)際表示的 C 類型(Win32) |
boolean | jboolean | unsigned char |
byte | jbyte | signed char |
char | jchar | unsigned short |
short | jshort | short |
int | jint | long |
long | jlong | __int64 |
float | jfloat | float |
double | jdouble | double |
void | void | N/A |
2> JNI字符串函數(shù)
JNI函數(shù) | 描述 | 版本 |
GetStringChars ReleaseStringChars | 獲得/釋放一個(gè)Unicode格式的字符串指針,可能返回一個(gè)字符串的副本 | JDK 1.1 |
GetStringUTFChars ReleaseStringUTFChars | 獲得/釋放一個(gè)UTF-8格式的字符串指針,可能返回一個(gè)字符串的副本 | JDK 1.1 |
GetStringLength | 返回Unicode格式字符串的長(zhǎng)度 | JDK 1.1 |
GetStringUTFLength | 返回UTF-8格式字符串的長(zhǎng)度 | JDK 1.1 |
NewString | 根據(jù)Unicode格式的C字符串創(chuàng)建一個(gè)Java字符串 | JDK 1.1 |
NewStringUTF | 根據(jù)UTF-8格式的C字符串創(chuàng)建一個(gè)Java字符串 | JDK 1.1 |
GetStringCritical ReleaseStringCritical | 獲得/釋放一個(gè)Unicode格式的字符串指針,可能返回一個(gè)字符串的副本【在該函數(shù)對(duì)區(qū)間內(nèi),不能使用任何JNI函數(shù)】 | JDK 1.2 |
GetStringRegion | 將Unicode格式的String復(fù)制到預(yù)分配的緩沖區(qū)中 | JDK 1.2 |
GetStringUTFRegion | 將UTF-8格式的String復(fù)制到預(yù)分配的緩沖區(qū)中 | JDK 1.2 |
備注:
首先,設(shè)置項(xiàng)目依賴的本地庫(kù),例如把opencv-246.jar引入到項(xiàng)目的lib庫(kù)中,opencv-246.jar在opencv的安裝目錄下的/build/java下。

其次,設(shè)置項(xiàng)目的native庫(kù),把opencv_java246.dll文件所在的目錄加入到Native library location中,opencv_java246.dll在opencv安裝目錄下的/build/java/x86或/build/java/x64中,前者是32位系統(tǒng)用的,后者64位。


新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注