栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

jni c回调java

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

jni c回调java

使用头文件将C语言中的标准实现通过预编译映射到自己定义的函数中,并在自己定义的函数中调用java函数来实现,这一思路怎么实现呢

首先,通过.h定义函数替换C库中的函数,比如将C中的fopen替换为test_print,新建test.h 文件

//
// Created by crow on 2022/6/1.
//

#ifndef CCDEMO_TEST_H
#define CCDEMO_TEST_H

#endif //CCDEMO_TEST_H

#include 

#define fopen test_print

 新建test.c实现定义的test_print方法,在c里面通过jni调用java代码,要获取JavaVM,然后通过JavaVM获取到当前线程的JNIEnv,代码如下

//
// Created by crow on 2022/6/1.
//

#include "test.h"
#include 
#include 

JavaVM *javaVm;


jstring charToJstring(JNIEnv *env, const char *pat) {
    jsize len = strlen(pat);

    jclass strClass = (*env)->FindClass(env, "java/lang/String");
    jstring encoding = (*env)->NewStringUTF(env, "utf-8");

    jmethodID jmethodId = (*env)->GetMethodID(env, strClass, "","([BLjava/lang/String;)V");
    jbyteArray bytes = (*env)->NewByteArray(env, len);

    (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *) pat);
    return (jstring) (*env)->NewObject(env, strClass, jmethodId, bytes, encoding);
}

jstring test_print(const char* filename, const char* mode) {
    JNIEnv *env = NULL;
    if ((*javaVm)->AttachCurrentThread(javaVm, &env, NULL) != JNI_OK) {
        return NULL;
    }

    jclass clazz = (*env)->FindClass(env, "com/sun/android/ccdemo/MainActivity");
    jobject jobj = (*env)->AllocObject(env, clazz);
    jmethodID  jmethodId = (*env)->GetMethodID(env, clazz, "printLine",
                                               "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
    jstring jFileName = charToJstring(env, filename);
    jstring jMode = charToJstring(env, mode);
    return (*env)->CallObjectMethod(env, jobj, jmethodId, jFileName, jMode);
}

JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
    javaVm = vm;
    JNIEnv *env = NULL;
    jint result;

    if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_6) == JNI_OK) {
        result = JNI_VERSION_1_6;
    }
    else if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_4) == JNI_OK) {
        result = JNI_VERSION_1_4;
    }
    else {
        result = JNI_VERSION_1_2;
    }

    return result;
}

然后通过调用fopen即可实现调用test_print,如在native方法的实现中进行如下调用

 在调用native方法的地方进行调用即可如在MainActivity里面进行调用,如下

   private void readFile() {
        String path = "/storage/emulated/0/document/example2.txt";
        Log.e("crow", printFirstLine(path, "r"));
         
   }
   

    public native String printFirstLine(String fileName, String mode);

    public String printLine(String fileName, String mode) {
        RandomAccessFile randomAccessFile = null;
        try {
            randomAccessFile = new RandomAccessFile(fileName, mode);
            return randomAccessFile.readLine();
        } catch (IOException e) {
            return null;
        } finally {
            try {
                if (null != randomAccessFile)
                    randomAccessFile.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            Log.e("crow", "printLine: finally " );
        }
    }

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/943733.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号