Jni基础-jni交互

689 阅读2分钟

vs+eclipse组合开发Jni

1,定义native方法,使用javah命令生成头文件。
2,将生成的头文件和jni.h,jni_md.h添加到vs中。
3,实现“生成的头文件”的函数。

关于JNIEnv 如果是c++,JNIEnv 是一个对象,否则,是结构体。 所以如果是使用C语言(.c)则(*env).xxxx ,否则是env->形式。

#ifdef __cplusplus   
typedef JNIEnv_ JNIEnv;
#else
typedef const struct JNINativeInterface_ *JNIEnv;
#endif

extern "C" 的意思是统一采用C的编译,因为在C里是不允许函数的重载,在c++可以。因为包保证Java_x_x_x的唯一性。


#if defined(__cplusplus)

typedef _JNIEnv JNIEnv;

typedef _JavaVM JavaVM;

#else

typedef const struct JNINativeInterface* JNIEnv;

typedef const struct JNIInvokeInterface* JavaVM;

#endif

如果是C++,JNIEnv 是 JNIEnv 对象,如果是C 则是 JNINativeInterface 结构体的 指针别名(一级指针)。

JNINativeInterface的结构内容


struct JNINativeInterface_ {

void *reserved0;

void *reserved1;

void *reserved2;

void *reserved3;

jint (JNICALL *GetVersion)(JNIEnv *env);

//xxxxxx

}

其内容都是方法指针构成。关于方法指针的运用

C/C++调用Java方法

调用Native方法,获取UUID,UUID是调用Java的方法来获取,在返回到给Java层。

env->GetStaticMethodID 为静态方法。

JNIEXPORT jstring JNICALL Java_com_eric_MainTest_getStringNativeMethod(JNIEnv 
*env, jobject jobj){

       char * ch = "c char *";
       jclass jlcz = env->GetObjectClass(jobj);
       jmethodID methodID = env->GetStaticMethodID(jlcz, "getUUid", 
"()Ljava/lang/String;");
       jstring s = (jstring)env->CallStaticObjectMethod(jlcz, methodID);
       return s;
}
   private static String getUUid() {
      String s = UUID.randomUUID().toString();
      return s;
   }
   public native String getStringNativeMethod();

调2个int参数的方法,并返回值后输出

   //java方法
   public int add(int a, int b) {
      int c = a + b;
      return c;
   }





JNIEXPORT void JNICALL Java_com_eric_MainTest_nativeAdd(JNIEnv *env, jobject jobj, 
jint jinta, jint jintb){
       jclass jcls = env->GetObjectClass(jobj);
       jmethodID methodID = env->GetMethodID(jcls, "add", "(II)I");

       jint j = env->CallIntMethod(jobj, methodID, jinta, jintb);
       printf("-- %d \n", j);
}


C修改Java变量

//java变量
private int age = 10;


JNIEXPORT void JNICALL Java_com_eric_MainTest_changeAge(JNIEnv * env, jobject 
jobj){
       jclass jlcz = env->GetObjectClass(jobj);
       jfieldID fieldID = env->GetFieldID(jlcz, "age", "I");
       env->SetIntField(jobj, fieldID, 12);
}

在C/C++创建Java层对象,并返回。

      Point point = mainTest.getPoint();

      System.out.println("point: x: " + point.getX() +"   y: " + point.getY());
      
       private native Point getPoint();


JNIEXPORT jobject JNICALL Java_com_eric_MainTest_getPoint(JNIEnv * env, jobject 
jobj){
       jclass j_point_class = env->FindClass("com/eric/Point");
       jmethodID methodID = env->GetMethodID(j_point_class, "<init>", "(II)V");

       jobject jobject = env->NewObject(j_point_class, methodID, 11, 22);
       jclass point_class = env->GetObjectClass(jobject);
       if (j_point_class == point_class){
              printf("== \n");
       }
       else{
              printf("!= \n");
       }
       jmethodID methodID1 = env->GetMethodID(point_class, "setX", "(I)V");
       jint jint =   env->CallIntMethod(jobject, methodID1,2);
       printf("jint:  %d " ,jint);
       return jobject;
}

全局引用


jstring jGlobalString;

JNIEXPORT void JNICALL Java_com_eric_Test2_saveGlobalString(JNIEnv * env, jobject jobj, jstring jstr){
	jGlobalString = (jstring)env->NewGlobalRef(jstr);

}

JNIEXPORT jstring JNICALL Java_com_eric_Test2_getGlobalString
(JNIEnv * env, jobject jobj){

	return jGlobalString;

}

JNIEXPORT void JNICALL Java_com_eric_Test2_delteGlobalRef
(JNIEnv * env, jobject jobj){
	env->DeleteGlobalRef(jGlobalString);
}

异常处理


JNIEXPORT void JNICALL Java_com_eric_Test2_exception(JNIEnv *env, jobject jobj){

	jclass jclz = env->GetObjectClass(jobj);
	jfieldID f_id = env->GetStaticFieldID(jclz, "name3", "Ljava/lang/String;");

	jthrowable throwable = env->ExceptionOccurred(); // occurred 发生


	if (throwable){  //如果产生了异常
		env->ExceptionClear(); // 清除异常

		jclass jthrowclz = env->FindClass("java/lang/RuntimeException");
		env->ThrowNew(jthrowclz, "run time cuo cuole");//抛向java
		return;
	}
}

C代码

Java代码

一般开发流程