美文网首页Android
JNI Java与C的相互调用与基本操作

JNI Java与C的相互调用与基本操作

作者: 潇风寒月 | 来源:发表于2018-09-21 15:42 被阅读26次

    Java和Jni的类型对照表

    image

    引用类型对照表

    image

    一.Java调用C函数

    1.字符串拼接

    public native String concatString(String a, String b);
    
    /**
     * 字符串拼接
     */
    extern "C"
    JNIEXPORT jstring JNICALL
    Java_com_xfhy_ndkdemo_MainActivity_concatString(JNIEnv *env, jobject instance, jstring a_, jstring b_) {
        //jstring 转 char*
        const char *a = env->GetStringUTFChars(a_, 0);
        const char *b = env->GetStringUTFChars(b_, 0);
    
        //释放拷贝的内存
        /*
         * 第一个参数指定一个jstring变量,即是要释放的本地字符串的来源。
            第二个参数就是要释放的本地字符串
         * */
        env->ReleaseStringUTFChars(a_, a);
        env->ReleaseStringUTFChars(b_, b);
        //动态申请一个地址空间
        char *c = (char *) malloc(strlen(a) + strlen(b));
        strcpy(c, a);
        strcat(c, b);
    
        //将char* 转jstring
        return env->NewStringUTF(c);
    }
    

    2.比较字符串

    public native int compareString(String a, String b);
    
    /**
     * 比较字符串
     */
    extern "C"
    JNIEXPORT jint JNICALL
    Java_com_xfhy_ndkdemo_MainActivity_compareString(JNIEnv *env, jobject instance, jstring a_, jstring b_) {
        const char *a = env->GetStringUTFChars(a_, 0);
        const char *b = env->GetStringUTFChars(b_, 0);
    
    
        env->ReleaseStringUTFChars(a_, a);
        env->ReleaseStringUTFChars(b_, b);
    
        return strcmp(a, b);
    }
    

    3. 数组求和

    public native int sumArray(int[] array);
    
    /**
     * 数组求和
     */
    extern "C"
    JNIEXPORT jint JNICALL
    Java_com_xfhy_ndkdemo_MainActivity_sumArray(JNIEnv *env, jobject instance, jintArray array_) {
        //从java数组获取数组指针
        jint *array = env->GetIntArrayElements(array_, NULL);
    
        int sum = 0;
        int len = env->GetArrayLength(array_);
        for (int i = 0; i < len; i++) {
            sum += array[i];
        }
    
        env->ReleaseIntArrayElements(array_, array, 0);
    
        return sum;
    }
    

    二.C调用Java方法

    public class CallJava {
        static {
            System.loadLibrary("native-lib");
        }
    
        private static final String TAG = "CallJava";
    
        public native void callVoidMethod();
    
        public void hello() {
            Log.e(TAG, "Java的hello方法");
        }
    }
    
    /**
     * 调用java的方法
     */
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_xfhy_ndkdemo_CallJava_callVoidMethod(JNIEnv *env, jobject instance) {
        //通过反射调用java中的方法
        //找class 使用FindClass方法,参数就是要调用的函数的类的完全限定名,但是需要把点换成/
        jclass clazz = env->FindClass("com/xfhy/ndkdemo/CallJava");
        //获取对应的函数: 参数1:类class,参数2:方法名,参数3:方法签名
        //ps:方法签名的获取:进入build->intermediates->classes->debug目录下,使用javap -s 类的完全限定名,就能获得函数签名
        jmethodID method = env->GetMethodID(clazz, "hello", "()V");
        //实例化该class对应的实例  使用AllocObject方法,使用clazz创建该class的实例。
        jobject object = env->AllocObject(clazz);
        //调用方法
        env->CallVoidMethod(object, method);
    }
    

    三.在C中打印日志

    在CMakeLists.txt中加入

    find_library(
                 log-lib
    
    
                  log )
    
    target_link_libraries( 
                           native-lib
    
                           ${log-lib} )
    

    然后在cpp文件中加入

    #include "android/log.h"
    
    #define LOG_TAG "JNI_TEST"
    #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
    #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
    #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
    

    使用方式:

    int a = 10;
    LOGE("xfhy   我是C代码中的日志    a=%d", a);
    
    LOGE("我是xfhy");
    

    相关文章

      网友评论

        本文标题:JNI Java与C的相互调用与基本操作

        本文链接:https://www.haomeiwen.com/subject/jazanftx.html