2025年3月29日 星期六 甲辰(龙)年 月廿八 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > Java

JNI接口操作实践(二)

时间:08-15来源:作者:点击数:45

前面介绍了JNI的基本规范以及JNI的接口的生成过程。本文通过一个jni_test 应用实践操作JNI的接口各种典型应用。

jni_test从jni的字符串,数组,基本类型,自定义类,C回调java静态方法,C回调Java的实例方法,C访问Java的静态变量,C访问Java的实例变量,Java传内存数据给C,C传内存数据给Java 共10个demo演示jni各种典型应用场景。

一、UI设计

通过修改active_main.xml(为了简单起见采用相对布局),或者直接使用design工具拖动布局(先拖一个layout线下布局,再在该布局上排上控件,类似MFC的UI设计原理),UI效果如下。

jni_test的UI界面

二、JIN接口的定义

Java JNI接口声明如下:

  • public native String stringFromJNI(String src);
  • public native String CallbackFuncTest();
  • public native int CallbackClassTest();
  • public native int CallbackStaticVarTest();
  • public native int CallbackVarTest(TestNative obj);
  • public native int add(int x,int y);
  • public native int [] updateArray(int [] src,int len);
  • public native void passmem2C(int [] src,int len);
  • public native int [] getmem2C();

三、在native层jni实现如下:

  • extern "C" JNIEXPORT jstring JNICALL
  • Java_com_example_jni_1test_MainActivity_stringFromJNI(
  • JNIEnv* env,
  • jobject /* this */,
  • jstring src) {
  • std::string hello = "Hello3 from C++";
  • const char* native_string = env->GetStringUTFChars(src, NULL);
  • std::string temp(native_string);
  • std::string dst = hello+temp;
  • env->ReleaseStringUTFChars(src, native_string);
  • return env->NewStringUTF(dst.c_str());
  • }
  • //回调java 静态的方法
  • extern "C" JNIEXPORT jstring Java_com_example_jni_1test_MainActivity_CallbackFuncTest(
  • JNIEnv* env,
  • jobject /* this */ ){
  • jclass mJclass;
  • jstring mJstring;
  • jmethodID mJStaticmethodID;
  • //1.从classpath路径下搜索ClassMethod这个类,并返回该类的Class对象
  • int i = 0;
  • mJclass = env->FindClass("com/example/jni_test/TestNative"); //JNIEnv*, const char*
  • if (mJclass == NULL) {
  • LOGI("test","callJavaStaticMethod==>>mJclass==NULL==>>%s", "");
  • return env->NewStringUTF("CallbackTest is failed");
  • }
  • // 2、从clazz类中查找callStaticMethod方法
  • mJStaticmethodID = env->GetStaticMethodID(mJclass,
  • "settext",
  • "(Ljava/lang/String;)V"); //JNIEnv*, jclass, const char*, const char*
  • if (mJStaticmethodID == NULL) {
  • LOGI("test","=====>>>can not foud callStaticMethod");
  • return env->NewStringUTF("CallbackFuncTest is failed");
  • }
  • mJstring= env->NewStringUTF("settext is now");
  • env->CallStaticVoidMethod(mJclass, mJStaticmethodID, mJstring);
  • // 删除局部引用
  • env->DeleteLocalRef(mJstring);
  • env->DeleteLocalRef(mJclass);
  • return env->NewStringUTF("CallbackFuncTest is now");
  • }
  • //回调java中的类
  • extern "C" JNIEXPORT jint Java_com_example_jni_1test_MainActivity_CallbackClassTest(
  • JNIEnv* env,
  • jobject /* this */ ) {
  • jclass mJclass = NULL;
  • jmethodID jmethodID_Construct; //构造方法ID
  • jmethodID jmethodID_Method_Instance; //方法的ID
  • jmethodID jmethodID_Method_Instance2; //方法的ID
  • jobject jobjectMyClass; //类的实例
  • //1、从classpath路径下搜索ClassMethod这个类,并返回该类的Class对象
  • mJclass = env->FindClass("com/example/jni_test/TestNative");
  • if (mJclass == NULL) {
  • printf("====FindClass not found \n");
  • return 0;
  • }
  • // 2、获取类的默认构造方法ID
  • jmethodID_Construct = env->GetMethodID(mJclass, "<init>", "(I)V");
  • if (jmethodID_Construct == NULL) {
  • printf("GetMethodID not found ==>>jmethodID_Construct");
  • return 0;
  • }
  • // 3、查找实例方法的ID
  • jmethodID_Method_Instance = env->GetMethodID(mJclass,
  • "setnum", "(I)V");
  • if (jmethodID_Method_Instance == NULL) {
  • return 0;
  • }
  • // 4、创建该类的实例 调用无参构造方法 如果其它构造方法,后面可传参数
  • jobjectMyClass = env->NewObject(mJclass, jmethodID_Construct,100); //JNIEnv*, jclass, jmethodID, ...
  • if (jobjectMyClass == NULL) {
  • return 0;
  • }
  • // 5、调用对象的实例方法
  • env->CallVoidMethod(jobjectMyClass, jmethodID_Method_Instance,
  • 100); //JNIEnv*, jobject, jmethodID, ...
  • // 3、查找实例方法的ID
  • jmethodID_Method_Instance2 = env->GetMethodID(mJclass,
  • "getnum", "()I");
  • if (jmethodID_Method_Instance2 == NULL) {
  • return 0;
  • }
  • int ret;
  • ret=env->CallIntMethod(jobjectMyClass, jmethodID_Method_Instance2); //JNIEnv*, jobject, jmethodID, ...
  • // 删除局部引用
  • env->DeleteLocalRef(jobjectMyClass);
  • return ret;
  • }
  • //回调java中的类中静态变量
  • extern "C" JNIEXPORT jint Java_com_example_jni_1test_MainActivity_CallbackStaticVarTest(
  • JNIEnv* env,
  • jobject /* this */ ) {
  • jclass clazz;
  • jfieldID fid;
  • int test;
  • //1.获取ClassField类的Class引用
  • clazz = env->FindClass("com/example/jni_test/TestNative");
  • if (clazz == NULL) { // 错误处理
  • return 0;
  • }
  • //2.获取ClassField类静态变量test的属性ID
  • fid = env->GetStaticFieldID(clazz, "iVar", "I");
  • if (fid == NULL) {
  • return 0;
  • }
  • // 3.获取静态变量test的值
  • test = env->GetStaticIntField(
  • clazz,
  • fid);
  • LOGI("test","test = %d\n", test);
  • // 4.修改静态变量num的值
  • jint ret = 55;
  • env->SetStaticIntField(clazz, fid, ret);
  • test = env->GetStaticIntField(
  • clazz,
  • fid);
  • // 删除属部引用
  • env->DeleteLocalRef(clazz);
  • return test;
  • }
  • extern "C" JNIEXPORT int Java_com_example_jni_1test_MainActivity_CallbackVarTest(
  • JNIEnv* env,
  • jobject /* this */,jobject obj) {
  • jclass clazz;
  • jfieldID fid;
  • jstring j_str;
  • jstring j_newStr;
  • const char *c_str = NULL;
  • // 1.获取AccessField类的Class引用
  • clazz = env->GetObjectClass(obj);
  • if (clazz == NULL) {
  • return 0;
  • }
  • // 2. 获取AccessField类实例变量str的属性ID
  • fid = env->GetFieldID(clazz, "str", "Ljava/lang/String;");
  • if (clazz == NULL) {
  • return 0;
  • }
  • // 3. 获取实例变量str的值
  • j_str = static_cast<jstring>(env->GetObjectField(obj, fid)); //JNIEnv*, jobject, jfieldID
  • if (j_str == NULL) {
  • return 0;
  • }
  • // 4. 将unicode编码的java字符串转换成C风格字符串
  • c_str = env->GetStringUTFChars(j_str, NULL); //JNIEnv*, jstring, jboolean*
  • if (c_str == NULL) {
  • return 0;
  • }
  • LOGI("test","In C--->ClassField.str = %s\n", c_str);
  • env->ReleaseStringUTFChars(j_str, c_str); //JNIEnv*, jstring, const char*
  • // 5. 修改实例变量str的值
  • j_newStr = env->NewStringUTF("This is new String");
  • if (j_newStr == NULL) {
  • return 0;
  • }
  • env->SetObjectField(obj, fid, j_newStr); //JNIEnv*, jobject, jfieldID, jobject
  • // 6.删除局部引用
  • env->DeleteLocalRef(clazz); //JNIEnv*, jobject
  • env->DeleteLocalRef(j_str); //JNIEnv*, jobject
  • env->DeleteLocalRef(j_newStr); //JNIEnv*, jobject
  • //env->DeleteLocalRef(env,fid);//JNIEnv*, jobject 返回的非object,不能使用 DeleteLocalRef
  • //使用NewObject就会返回创建出来的实例的局部引用 可 DeleteLocalRef
  • return 1;
  • }
  • extern "C" JNIEXPORT jint JNICALL Java_com_example_jni_1test_MainActivity_add
  • (JNIEnv *env, jobject, jint x, jint y){
  • int x1 = x;
  • int y1 = y;
  • int sum = (x1+y1)*200;
  • __android_log_print(ANDROID_LOG_DEBUG,"test","hello5 world");
  • LOGD("test","hello sum is %d",sum);
  • //printf("hello3 world");
  • // std::cout<<"hello4 world"<<std::endl;
  • return sum;
  • }
  • extern "C" JNIEXPORT jintArray JNICALL Java_com_example_jni_1test_MainActivity_updateArray
  • (JNIEnv *env, jobject, jintArray src,jint len)
  • {
  • jintArray dst;
  • jint *cPArray = env->GetIntArrayElements(src, NULL);
  • if (cPArray == NULL) {
  • return 0; // JVM复制原始数据到缓冲区失败
  • }
  • // jint i;
  • for(int i=0;i<len;i++)
  • {
  • cPArray[i]=cPArray[i]+100;
  • LOGD("test","cPArray %d",cPArray[i]);
  • }
  • //给java层返回数组方式1
  • int cInts[len]; //定义一个数组
  • for (int i = 0; i < len; i++) {
  • cInts[i] = cPArray[i];
  • }
  • dst = env->NewIntArray(len);
  • if (dst == NULL) {
  • return NULL; /* out of memory error thrown */
  • }
  • //move from the temp structure to the java structure 将native数组转换为java层数组
  • env->SetIntArrayRegion(dst, 0, sizeof(cInts) / sizeof(cInts[0]),
  • cInts);
  • env->ReleaseIntArrayElements(src, cPArray, 0); // 释放可能复制的缓冲区
  • return dst;
  • }
  • extern "C" JNIEXPORT void JNICALL Java_com_example_jni_1test_MainActivity_passmem2C
  • (JNIEnv *env, jobject, jintArray src,jint len) {
  • jintArray dst;
  • int *cPArray = env->GetIntArrayElements(src, NULL);
  • if (cPArray == NULL) {
  • return ; // JVM复制原始数据到缓冲区失败
  • }
  • for(int i=0;i<len;i++)
  • {
  • *(cPArray+i)=i;
  • LOGD("test","cPArray %d", *(cPArray+i));
  • }
  • env->ReleaseIntArrayElements(src, cPArray, 0); // 释放可能复制的缓冲区
  • }
  • extern "C" JNIEXPORT jintArray JNICALL Java_com_example_jni_1test_MainActivity_getmem2C
  • (JNIEnv *env, jobject){
  • jintArray dst;
  • int *p = (int *)malloc(10);
  • if(!p)
  • {
  • LOGD("test","malloc is failed");
  • }
  • for(int i=0;i<10;i++)
  • {
  • *(p+i)=i;
  • LOGD("test","navtive cPArray %d", *(p+i));
  • }
  • dst = env->NewIntArray(10);
  • if (dst == NULL) {
  • return NULL; /* out of memory error thrown */
  • }
  • //move from the temp structure to the java structure 将native数组转换为java层数组
  • env->SetIntArrayRegion(dst, 0, 10,p);
  • return dst;
  • }
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门