native調用Java的普通屬性
- Java 代碼
public class JniUtils {
static{
System.loadLibrary("JNIEnvOne");
}
public String name = "liu";
//通路普通屬性
public native void modifField();
}
- C 代碼
//調用普通屬性
JNIEXPORT void JNICALL Java_com_liu_JniUtils_modifField
(JNIEnv * env, jobject obj){
//擷取類
jclass jclazz = (*env)->GetObjectClass(env, obj);
//擷取屬性,屬性簽名
jfieldID field = (*env)->GetFieldID(env, jclazz, "name", "Ljava/lang/String;");
//拿到屬性的值(JNI的)
//get<Type>Field 模式,不同的類型
jstring jojb = (*env)->GetObjectField(env, obj, field);
//轉成c的字元串
//isCopy 是否指派的意思。
jboolean isCopy = NULL;
char* c_str = (*env)->GetStringChars(env, jojb, &isCopy);
if (isCopy){
printf("%s\n", "this str is copy");
}
char* mid = "I am from C";
//拼接C的字元串
strcat(c_str, mid);
//set<Type>Field 模式
(*env)->SetObjectField(env, obj, field, (*env)->NewStringUTF(env, c_str));
//釋放
(*env)->ReleaseStringChars(env, jojb, c_str);
}
調用步驟:
- 擷取類。 (*env)->GetObjectClass(env, obj);
- 擷取屬性簽名。(*env)->GetFieldID(env, jclazz, “name”, “Ljava/lang/String;”);
- 拿到屬性的值。(*env)->GetObjectField(env, obj, field);
- 把值轉換成C可操作的類型。(*env)->GetStringChars(env, jojb, &isCopy);
- 操作屬性的值。strcat(c_str, mid)/重新指派等等
- 轉換成JNI需要的類型。((*env)->NewStringUTF(env, c_str))
- 設定到屬性裡面。SetObjectField
- 把建立的字元串釋放。(*env)->ReleaseStringChars(env, jojb, c_str);
native調用Java的靜态屬性
- Java 代碼
public class JniUtils {
static{
System.loadLibrary("JNIEnvOne");
}
public static String staticName = "liu";
//通路靜态屬性
public native void modifStaticField();
}
- C 代碼
//擷取靜态屬性
JNIEXPORT void JNICALL Java_com_liu_JniUtils_modifStaticField
(JNIEnv * env, jobject obj){
//先擷取jclass
jclass cls = (*env)->GetObjectClass(env, obj);
//擷取屬性簽名
jfieldID fid = (*env)->GetStaticFieldID(env, cls, "staticName", "Ljava/lang/String;");
//擷取屬性
jstring field = (*env)->GetStaticObjectField(env, cls, fid);
//轉換成c的類型
char* str = (*env)->GetStringChars(env, field, NULL);
char* s = "static str";
strcat(s, str);
jstring result = (*env)->NewStringUTF(env, s);
(*env)->SetStaticObjectField(env, cls, fid, result);
(*env)->ReleaseStringChars(env, field, str);
}
步驟:
- 擷取類
- 擷取屬性簽名
- 擷取屬性
- 轉換成C可操作的類型
- 操作值
- 轉換成JNI需要的類型
- 設定屬性
- 釋放資源
native調用Java的普通方法
- Java代碼
public class JniUtils {
static{
System.loadLibrary("JNIEnvOne");
}
//通路普通方法
public native void callMethod(int count);
public void normalMethod(int count){
System.out.println("普通方法被調用了。count:"+count);
}
}
- C 代碼
//調用普通方法
JNIEXPORT void JNICALL Java_com_liu_JniUtils_callMethod
(JNIEnv * env, jobject obj,jint count){
//擷取類
jclass cls = (*env)->GetObjectClass(env, obj);
//擷取方法簽名
jmethodID mid = (*env)->GetMethodID(env, cls, "normalMethod", "(I)V");
//調用方法
(*env)->CallObjectMethod(env, obj, mid, count);
}
步驟:
- 擷取類
- 擷取方法簽名
- 調用方法
native調用Java的靜态方法
- Java 代碼
public class JniUtils {
static{
System.loadLibrary("JNIEnvOne");
}
//通路靜态方法
public native void callStaticMethod();
public static void staticMethod(){
System.out.println("static 方法被調用了。count:");
}
}
- C 代碼
//調用靜态方法
JNIEXPORT void JNICALL Java_com_liu_JniUtils_callStaticMethod
(JNIEnv * env, jobject obj, jint count){
//擷取類
jclass cls = (*env)->GetObjectClass(env, obj);
//擷取方法簽名
jmethodID mid = (*env)->GetStaticMethodID(env, cls, "staticMethod", "()V");
//調用方法
(*env)->CallStaticVoidMethod(env, cls, mid);
}
Java層調用native,傳回亂碼問題及調用構造方法
- Java 代碼
public class JniUtils {
static{
System.loadLibrary("JNIEnvOne");
}
//通路構造方法
public native void callConstructMethod();
public String name = "liu";
}
- C 代碼
//解決字元串的亂碼問題,及通路類的構造器
//通過new String(byte[],charset)。轉換編碼來解決亂碼問題
jstring conv_str_to_java(JNIEnv* env, char* str){
//先找到類
jclass cls = (*env)->FindClass(env, "java/lang/String");
//擷取構造器的方法簽名
jmethodID mid = (*env)->GetMethodID(env, cls, "<init>", "([BLjava/lang/String;)V");
//需要轉換的字元串長度
int arr_len = strlen(str);
//jbyte-char。初始化一個同等長度的字元數組
jbyteArray arr = (*env)->NewByteArray(env, arr_len);
//str數組指派到jbytArray
(*env)->SetByteArrayRegion(env, arr, , arr_len, str);
//把需要的編碼,轉換成JNI需要的類型
jstring charsetName = (*env)->NewStringUTF(env, "GB2312");
//調用String的構造方法,初始化String類
jstring result = (*env)->NewObject(env, cls, mid, arr, charsetName);
return result;
}
//調用普通屬性
JNIEXPORT void JNICALL Java_com_liu_JniUtils_callConstructMethod
(JNIEnv * env, jobject obj){
//擷取類
jclass jclazz = (*env)->GetObjectClass(env, obj);
//擷取屬性,屬性簽名
jfieldID field = (*env)->GetFieldID(env, jclazz, "name", "Ljava/lang/String;");
//拿到屬性的值(JNI的)
//get<Type>Field 模式,不同的類型
jstring jojb = (*env)->GetObjectField(env, obj, field);
//轉成c的字元串
char* c_str = (*env)->GetStringChars(env, jojb,NULL);
char* mid = "我是C的字元串";
//拼接C的字元串
strcat(c_str, mid);
//set<Type>Field 模式
//這樣是有亂碼的
//(*env)->SetObjectField(env, obj, field, (*env)->NewStringUTF(env, c_str));
//通過上面的函數轉換後,就沒有亂碼了
(*env)->SetObjectField(env, obj, field, conv_str_to_java(env,c_str));
//釋放
(*env)->ReleaseStringChars(env, jojb, c_str);
}
native調用Java的普通的類的方法
- Java 代碼
public class JniUtils {
static{
System.loadLibrary("JNIEnvOne");
}
//通路普通類的普通方法
public native long callNormalClassMethod();
}
- C 代碼
//通路普通類的方法
JNIEXPORT jlong JNICALL Java_com_liu_JniUtils_callNormalClassMethod
(JNIEnv * env, jobject obj){
//找到類
jclass cls = (*env)->FindClass(env, "java/util/Date");
//擷取構造方法的簽名
jmethodID construct_id = (*env)->GetMethodID(env, cls, "<init>", "()V");
//初始化 類
jobject date_obj = (*env)->NewObject(env, cls,construct_id);
//擷取方法的簽名
jmethodID mid = (*env)->GetMethodID(env, cls, "getTime", "()J");
//通路方法
jlong t = (*env)->CallLongMethod(env, date_obj, mid);
return t;
}
檢視類屬性和方法的簽名
- cd native方法生成的類的檔案夾下
- 執行javap -s -p xx.xx.JniUtils