美文网首页Android JNIAndroid知识
jni 中较为复杂的数据类型(String和数组)

jni 中较为复杂的数据类型(String和数组)

作者: 战五渣_lei | 来源:发表于2017-05-29 11:12 被阅读39次

    前言

    本文承接 之前的
    <a href="http://www.jianshu.com/p/476aae319808">jni简单数据</a>,采用String和数组的的类型传递和返回参数,以深入对于jni的了解

    String 类型

    修改 JniHello.java

    
    /**
     * Created by act64 on 2017/5/25.
     */
    
    public class JniHello {
        static{
            System.loadLibrary("nativehello");
        }
    
    
    public static void main(String[]arg){
        JniHello jniHello =new JniHello();
        System.out.println( jniHello.hello("world"));
    
    }
        public native String hello(String str);
    }
    
    

    为了方便搞明白数据类型和参数以及对于的描述符,还是偷懒用javah生成

    //在terminal里面输入
    javac JniHello.java
    javah JniHello
    

    这样目录下就生成了JniHello.h文件
    打开 JniHello.h

    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class JniHello */
    
    #ifndef _Included_JniHello
    #define _Included_JniHello
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
     * Class:     JniHello
     * Method:    hello
     * Signature: (Ljava/lang/String;)Ljava/lang/String;
     */
    JNIEXPORT jstring JNICALL Java_JniHello_hello
      (JNIEnv *, jobject, jstring);
    
    #ifdef __cplusplus
    }
    #endif
    #endif
    

    我们在意的是Signature 和JNICALL Java_JniHello_hello的参数和返回值,将这些参数运用到我们上一篇简书写的hello.c中

    #include <stdio.h>
    #include <jni.h>
    jstring c_hello(JNIEnv * env, jobject mJobject,jstring val){
        const jbyte *str;
        str = (*env)->GetStringUTFChars(env, val, NULL);
        if (str == NULL) {
            return NULL; /* OutOfMemoryError already thrown */
        }
        printf("java IN %s", str);
        (*env)->ReleaseStringUTFChars(env, val, str);
    
        return (*env)->NewStringUTF(env, "helloJNIStr");
    }
    
    const JNINativeMethod methods[]={
        {"hello","(Ljava/lang/String;)Ljava/lang/String;",(jstring *)c_hello},
    };
    
    
    JNIEXPORT jint JNICALL
    JNI_OnLoad(JavaVM *jvm, void *reserved)
    {
        JNIEnv *env;
        jclass cls;
        if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) {
    return JNI_ERR; /* JNI version not supported */
        }
        cls = (*env)->FindClass(env, "JniHello");
        if (cls == NULL) {
            return JNI_ERR;
        }
    
        if((*env)->RegisterNatives(env,cls,methods,1)<0){
            return JNI_ERR;
        }
        return JNI_VERSION_1_4;
    }
    
    

    然后编译文件 ,命令在上一篇简书中有详细介绍,可以去翻一下 <a href="http://www.jianshu.com/p/476aae319808">jni简单数据</a>

     gcc -fPIC -I /usr/lib/jvm/java-1.7.0-openjdk-amd64/include -shared -o libnativehello.so  hello.c
    
    export LD_LIBRARY_PATH=./
    
    javac JniHello.java
    
    java JniHello
    
    

    结果如下

    String输出.png

    数组

    String就是这样传的,数组也是类似的,改写java文件和c文件

    
    /**
     * Created by act64 on 2017/5/25.
     */
    
    public class JniHello {
        static{
            System.loadLibrary("nativehello");
        }
    
    
    public static void main(String[]arg){
        JniHello jniHello =new JniHello();
        int [] a={1,2,3};
        int []b=jniHello.hello(a);
        for (int i=0;i<3 ;i++ ) {
            System.out.println( b[i]);
        }
        
    
    }
        public native int[] hello(int[] ints);
    }
    
    

    hello.c

    #include <stdio.h>
    #include <jni.h>
    #include <stdlib.h>
    jintArray c_hello(JNIEnv * env, jobject mJobject,jintArray arr){
        jint *carr;
        jint i, sum = 0;
    //将jintarray转为c++的int数组指针
        carr = (*env)->GetIntArrayElements(env, arr, NULL);
        if (carr == NULL) {
        return 0; /* exception occurred */
        }
    //获得数组长度
        jint length=(*env)->GetArrayLength(env,arr);
        jint *buff;
    //动态生成数组
    //需要头文件stdlib
    //并且malloc使用完后应该free
        buff=malloc(length*sizeof(jint));
        if (buff==NULL)
        {
    //使用完后,应该释放内存,下同
            (*env)->ReleaseIntArrayElements(env, arr, carr, 0);
            return 0;
            /* code */
        }
        for (i=0; i<length; i++) {
            sum += carr[i];
            buff[i]=sum*sum;
        }
    //创建新的intarray
    //用于返回给java
        jintArray reArray=(*env)->NewIntArray(env,length);
    //将c++数组的内容,拷贝到要返回给java的intarray去
        (*env)->SetIntArrayRegion(env,reArray,0,length,buff);
        (*env)->ReleaseIntArrayElements(env, arr, carr, 0);
        printf("sum = %d\n", sum);
        free(buff); 
        return reArray;
    }
    //描述符和返回类型
    //利用javah命令可以看到
    const JNINativeMethod methods[]={
        {"hello","([I)[I",(jintArray *)c_hello},
    };
    
    
    JNIEXPORT jint JNICALL
    JNI_OnLoad(JavaVM *jvm, void *reserved)
    {
        JNIEnv *env;
        jclass cls;
        if ((*jvm)->GetEnv(jvm, (void **)&env, JNI_VERSION_1_4)) {
    return JNI_ERR; /* JNI version not supported */
        }
        cls = (*env)->FindClass(env, "JniHello");
        if (cls == NULL) {
            return JNI_ERR;
        }
    
        if((*env)->RegisterNatives(env,cls,methods,1)<0){
            return JNI_ERR;
        }
        return JNI_VERSION_1_4;
    }
    
    
    
    

    然后运行编译命令。看输出

    gcc -fPIC -I /usr/lib/jvm/java-1.7.0-openjdk-amd64/include -shared -o libnativehello.so  hello.c
    
    javac JniHello.java
    
    java JniHello
    
    

    输出如下

    图片.png

    结语

    本文主要讲了 jni中较为复杂的数据类型,字符串和数组的传递,下一篇将要讲一讲类对象的传递

    相关文章

      网友评论

        本文标题:jni 中较为复杂的数据类型(String和数组)

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