JNI小记
本文参考《较详细的介绍JNI》一文,并添加了一些方法,代码已经过测试,留待日后工作使用。关于JNI的HelloWorld的例子,就不赘述了。
java代码:
1 package com.chnic.service; 2 3 import com.chnic.bean.Order; 4 5 public class Business { 6 static{ 7 System.loadLibrary("FruitFactory"); 8 } 9 10 public Business(){ 11 12 } 13 14 public native double getPrice(String name); 15 public native Order getOrder(String name, int amount); 16 public native Order getRamdomOrder(); 17 public static native void analyzeOrder(Order order); 18 19 public native void showArray(int []nums); 20 21 public native int[] getIntArray(); 22 23 public native String[] getStringArray(String[] ss); 24 25 public native void test2DStringArray(String[][] ss); 26 27 public void notification(){ 28 System.out.println("Got a notification."); 29 } 30 31 public static void notificationByStatic(){ 32 System.out.println("Got a notification in a static method."); 33 } 34 35 public static void main(String...args){ 36 Business bus = new Business(); 37 System.out.println("price:"+bus.getPrice("Apple")); 38 System.out.println("-------------------------"); 39 40 System.out.println("price:"+bus.getPrice("Pear")); 41 System.out.println("-------------------------"); 42 43 System.out.println(bus.getOrder("Apple",23)); 44 System.out.println("-------------------------"); 45 46 System.out.println(bus.getRamdomOrder()); 47 System.out.println("-------------------------"); 48 49 Order order = new Order(); 50 order.setName("orange"); 51 Business.analyzeOrder(order); 52 System.out.println("-------------------------"); 53 54 int[]ia={1,2,3,4}; 55 bus.showArray(ia); 56 System.out.println("-------------------------"); 57 58 int[] iaa = bus.getIntArray(); 59 for(int i:iaa){ 60 System.out.println(i); 61 } 62 System.out.println("-------------------------"); 63 64 String[]abc= {"aa","bb","cc","dd"}; 65 bus.getStringArray(abc); 66 System.out.println("-------------------------"); 67 68 String []abcd = bus.getStringArray(abc); 69 for(String s:abcd){ 70 System.out.println(s); 71 } 72 System.out.println("-------------------------"); 73 74 String[][]test = {{"一行1号","一行二号","一行三号"},{"二行一号","二行二号","二行三号"}}; 75 bus.test2DStringArray(test); 76 System.out.println("-------------------------"); 77 } 78 }
1 package com.chnic.bean; 2 3 public class Order { 4 5 private String name = "Fruit"; 6 private double price; 7 private int amount = 30; 8 9 public Order(){ 10 11 } 12 13 public int getAmount() { 14 return amount; 15 } 16 17 public void setAmount(int amount) { 18 this.amount = amount; 19 } 20 21 public String getName() { 22 return name; 23 } 24 25 public void setName(String name) { 26 this.name = name; 27 } 28 29 public double getPrice() { 30 return price; 31 } 32 33 public void setPrice(double price) { 34 this.price = price; 35 } 36 37 public String toString(){ 38 return "name is "+name+",price is "+price+",amount is "+amount+"."; 39 } 40 }
生成的com_chnic_service_Business.h头文件内容如下:
1 /* DO NOT EDIT THIS FILE - it is machine generated */ 2 #include <jni.h> 3 /* Header for class com_chnic_service_Business */ 4 5 #ifndef _Included_com_chnic_service_Business 6 #define _Included_com_chnic_service_Business 7 #ifdef __cplusplus 8 extern "C" { 9 #endif 10 /* 11 * Class: com_chnic_service_Business 12 * Method: getPrice 13 * Signature: (Ljava/lang/String;)D 14 */ 15 JNIEXPORT jdouble JNICALL Java_com_chnic_service_Business_getPrice 16 (JNIEnv *, jobject, jstring); 17 18 /* 19 * Class: com_chnic_service_Business 20 * Method: getOrder 21 * Signature: (Ljava/lang/String;I)Lcom/chnic/bean/Order; 22 */ 23 JNIEXPORT jobject JNICALL Java_com_chnic_service_Business_getOrder 24 (JNIEnv *, jobject, jstring, jint); 25 26 /* 27 * Class: com_chnic_service_Business 28 * Method: getRamdomOrder 29 * Signature: ()Lcom/chnic/bean/Order; 30 */ 31 JNIEXPORT jobject JNICALL Java_com_chnic_service_Business_getRamdomOrder 32 (JNIEnv *, jobject); 33 34 /* 35 * Class: com_chnic_service_Business 36 * Method: analyzeOrder 37 * Signature: (Lcom/chnic/bean/Order;)V 38 */ 39 JNIEXPORT void JNICALL Java_com_chnic_service_Business_analyzeOrder 40 (JNIEnv *, jclass, jobject); 41 42 /* 43 * Class: com_chnic_service_Business 44 * Method: showArray 45 * Signature: ([I)V 46 */ 47 JNIEXPORT void JNICALL Java_com_chnic_service_Business_showArray 48 (JNIEnv *, jobject, jintArray); 49 50 /* 51 * Class: com_chnic_service_Business 52 * Method: getIntArray 53 * Signature: ()[I 54 */ 55 JNIEXPORT jintArray JNICALL Java_com_chnic_service_Business_getIntArray 56 (JNIEnv *, jobject); 57 58 /* 59 * Class: com_chnic_service_Business 60 * Method: getStringArray 61 * Signature: ([Ljava/lang/String;)[Ljava/lang/String; 62 */ 63 JNIEXPORT jobjectArray JNICALL Java_com_chnic_service_Business_getStringArray 64 (JNIEnv *, jobject, jobjectArray); 65 66 /* 67 * Class: com_chnic_service_Business 68 * Method: test2DStringArray 69 * Signature: ([[Ljava/lang/String;)V 70 */ 71 JNIEXPORT void JNICALL Java_com_chnic_service_Business_test2DStringArray 72 (JNIEnv *, jobject, jobjectArray); 73 74 #ifdef __cplusplus 75 } 76 #endif 77 #endif
编写的CPP实现文件(文件名随意),内容如下:
1 #include <iostream.h> 2 #include <string.h> 3 #include "com_chnic_service_Business.h" 4 5 jobject getInstance(JNIEnv* env, jclass obj_class); 6 /* 7 * Class: com_chnic_service_Business 8 * Method: getPrice 9 * Signature: (Ljava/lang/String;)D 10 * 传递string参数,返回double值 11 */ 12 JNIEXPORT jdouble JNICALL Java_com_chnic_service_Business_getPrice(JNIEnv* env, 13 jobject obj, 14 jstring name) 15 { 16 const char* pname = env->GetStringUTFChars(name, NULL); 17 cout << "Before release: " << pname << endl; 18 19 if (strcmp(pname, "Apple") == 0) 20 { 21 env->ReleaseStringUTFChars(name, pname); 22 cout << "After release: " << pname << endl; 23 return 1.2; 24 } 25 else 26 { 27 env->ReleaseStringUTFChars(name, pname); 28 cout << "After release: " << pname << endl; 29 return 2.1; 30 } 31 } 32 33 /* 34 * Class: com_chnic_service_Business 35 * Method: getOrder 36 * Signature: (Ljava/lang/String;I)Lcom/chnic/bean/Order; 37 * 传递string、int参数,回调java类中的方法,并且返回一个java对象 38 */ 39 JNIEXPORT jobject JNICALL Java_com_chnic_service_Business_getOrder(JNIEnv* env, 40 jobject obj, 41 jstring name, 42 jint amount) 43 { 44 jclass order_class = env->FindClass("com/chnic/bean/Order"); 45 jobject order = getInstance(env, order_class); 46 47 jmethodID setName_method = env->GetMethodID(order_class, "setName", "(Ljava/lang/String;)V"); 48 env->CallVoidMethod(order, setName_method, name); 49 50 jmethodID setAmount_method = env->GetMethodID(order_class, "setAmount", "(I)V"); 51 env->CallVoidMethod(order, setAmount_method, amount); 52 53 return order; 54 } 55 56 /* 57 * Class: com_chnic_service_Business 58 * Method: getRamdomOrder 59 * Signature: ()Lcom/chnic/bean/Order; 60 * 无参方法,在C++中构造一个java对象返回 61 */ 62 JNIEXPORT jobject JNICALL Java_com_chnic_service_Business_getRamdomOrder(JNIEnv* env, 63 jobject obj) 64 { 65 jclass business_class = env->GetObjectClass(obj); 66 jobject business_obj = getInstance(env, business_class); 67 68 jmethodID notification_method = env->GetMethodID(business_class, "notification", "()V"); 69 env->CallVoidMethod(obj, notification_method); 70 71 jclass order_class = env->FindClass("com/chnic/bean/Order"); 72 jobject order = getInstance(env, order_class); 73 jfieldID amount_field = env->GetFieldID(order_class, "amount", "I"); 74 jint amount = env->GetIntField(order, amount_field); 75 cout << "amount: " << amount << endl; 76 return order; 77 } 78 79 80 /* 81 * Class: com_chnic_service_Business 82 * Method: analyzeOrder 83 * Signature: (Lcom/chnic/bean/Order;)V 84 * java中的静态方法,在C++中的实现,传递的参数是java对象,无返回值 85 */ 86 JNIEXPORT void JNICALL Java_com_chnic_service_Business_analyzeOrder (JNIEnv* env, 87 jclass cls, 88 jobject obj) 89 { 90 jclass order_class = env->GetObjectClass(obj); 91 jmethodID getName_method = env->GetMethodID(order_class, "getName", "()Ljava/lang/String;"); 92 jstring name_str = static_cast<jstring>(env->CallObjectMethod(obj, getName_method)); 93 const char* pname = env->GetStringUTFChars(name_str, NULL); 94 95 cout << "Name in Java_com_chnic_service_Business_analyzeOrder: " << pname << endl; 96 97 98 jmethodID notification_method_static = env->GetStaticMethodID(cls, "notificationByStatic", "()V"); 99 env->CallStaticVoidMethod(cls, notification_method_static); 100 101 } 102 103 /* 104 * 根据类,构造对应的对象返回 105 */ 106 jobject getInstance(JNIEnv* env, jclass obj_class) 107 { 108 jmethodID construction_id = env->GetMethodID(obj_class, "<init>", "()V"); 109 jobject obj = env->NewObject(obj_class, construction_id); 110 return obj; 111 } 112 113 /* 114 * Class: com_chnic_service_Business 115 * Method: showArray 116 * Signature: ([I)V 117 * 传递字符串数组,在C++中使用 118 */ 119 JNIEXPORT void JNICALL Java_com_chnic_service_Business_showArray 120 (JNIEnv* env, jobject job, jintArray jia) 121 { 122 jint* nums; 123 nums = env->GetIntArrayElements(jia,NULL); 124 125 jint length = env->GetArrayLength(jia); 126 cout<<"length:"<<length<<endl; 127 int i; 128 for(i=0;i<length;i++) 129 { 130 cout<<nums[i]<<endl; 131 } 132 } 133 134 /* 135 * Class: com_chnic_service_Business 136 * Method: getIntArray 137 * Signature: ()[I 138 * 返回整形数组 139 */ 140 JNIEXPORT jintArray JNICALL Java_com_chnic_service_Business_getIntArray 141 (JNIEnv *env, jobject job) 142 { 143 jsize col=10; 144 jint temp[10]={1,2,3,4,5,6,7,8,9,10}; 145 146 jintArray iarr = env->NewIntArray(col); 147 env->SetIntArrayRegion(iarr, 0, col, temp); 148 return iarr; 149 } 150 151 /* 152 * Class: com_chnic_service_Business 153 * Method: getStringArray 154 * Signature: ([Ljava/lang/String;)[Ljava/lang/String; 155 * 传递一个字符串数组,并且重新构造一个字符串数组,并返回 156 */ 157 JNIEXPORT jobjectArray JNICALL Java_com_chnic_service_Business_getStringArray 158 (JNIEnv* env, jobject job, jobjectArray joa) 159 { 160 //打印传递进来的字符串数组 161 jsize si = env->GetArrayLength(joa); 162 //cout<<si<<endl; 163 int i; 164 for(i=0;i<si;i++) 165 { 166 jstring str = (jstring)(env)->GetObjectArrayElement(joa, i); 167 //cout<<str<<endl; 168 const char* pname = env->GetStringUTFChars(str, NULL); 169 cout<<pname<<endl; 170 } 171 //构造新的字符串数组 172 jstring s1=env->NewStringUTF("123"); 173 jstring s2=env->NewStringUTF("456"); 174 jstring s3=env->NewStringUTF("789"); 175 jstring ss[3]={s1,s2,s3}; 176 177 178 jobjectArray swArray = env->NewObjectArray(3,env->FindClass("java/lang/String"), env->NewStringUTF("")); 179 //SetObjectArrayElement刷新数组元素内容 180 for(i = 0; i < 3; i++) 181 env->SetObjectArrayElement(swArray, i, ss[i]) ; 182 return swArray; 183 } 184 185 /** 186 * java传递二维字符串 187 * 188 */ 189 JNIEXPORT void JNICALL Java_com_chnic_service_Business_test2DStringArray 190 (JNIEnv *env, jobject obj, jobjectArray array) 191 { 192 int size = env->GetArrayLength(array); 193 for (int i = 0; i < size; i++) { 194 jobjectArray myarray =(jobjectArray) (env->GetObjectArrayElement(array, i)); 195 int length = env->GetArrayLength(myarray); 196 cout<<"length: "<<length<<endl; 197 for (int j = 0; j < length; j++) { 198 jstring string = (jstring)(env->GetObjectArrayElement(myarray, j)); 199 const char * chars = env->GetStringUTFChars(string, 0); 200 cout<<chars<<" "; 201 env->ReleaseStringUTFChars(string, chars); 202 } 203 cout<<endl; 204 } 205 }
生成动态链接库后,运行java的main方法,控制台打印信息如下:
Before release: Apple
After release: V
price:1.2
-------------------------
Before release: Pear
After release: X
price:2.1
-------------------------
name is Apple,price is 0.0,amount is 23.
-------------------------
Got a notification.
amount: 30
name is Fruit,price is 0.0,amount is 30.
-------------------------
Name in Java_com_chnic_service_Business_analyzeOrder: orange
Got a notification in a static method.
-------------------------
length:4
1
2
3
4
-------------------------
1
2
3
4
5
6
7
8
9
10
-------------------------
aa
bb
cc
dd
-------------------------
aa
bb
cc
dd
123
456
789
-------------------------
length: 3
一行1号 一行二号 一行三号
length: 3
二行一号 二行二号 二行三号
-------------------------
备注:1、使用Win7+eclipse+VC++6.0开发
2、VC++创建Win32 Dynamic-Link Library工程
3、在java调用native方法传递中文字符串时,若java工程或java文件格式不是UTF格式,会有乱码。