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

前言

本文承接 之前的
jni简单数据,采用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 
/* 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 
#include 
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;
}

然后编译文件 ,命令在上一篇中有详细介绍,可以去翻一下 jni简单数据

 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 
#include 
#include 
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; iNewIntArray(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和数组))