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;
}
}
一般开发流程