JNI语法

作者: Tony__Ren | 来源:发表于2019-04-08 14:39 被阅读0次
#define _CRT_SECURE_NO_WARNINGS
#include "com_dongnaoedu_jni_JniTest.h"
#include <string.h>
#include <stdlib.h>

//#include <Windows.h>

//函数实现
JNIEXPORT jstring JNICALL Java_com_dongnaoedu_jni_JniTest_getStringFromC
(JNIEnv *env, jclass jcls){
    //WinExec("C:\\Program Files (x86)\\Tencent\\QQ\\Bin\\QQScLauncher.exe",0);

    //JNIEnv 结构体指针
    //env二级指针
    //代表Java运行环境,调用Java中的代码
    //简单的实现
    //将C的字符串转为一个java字符串
    return (*env)->NewStringUTF(env,"C String");
}

JNIEXPORT jstring JNICALL Java_com_dongnaoedu_jni_JniTest_getString2FromC
(JNIEnv *env, jobject jobj, jint num){
    return (*env)->NewStringUTF(env,"C String2");
}

//每个native函数,都至少有两个参数(JNIEnv*,jclass或者jobject)
//1)当native方法为静态方法时:
//jclass 代表native方法所属类的class对象(JniTest.class)
//2)当native方法为非静态方法时:
//jobject 代表native方法所属的对象

//基本数据
//Java基本数据类型与JNI数据类型的映射关系
//Java类型->JNI类型->C类型

/*
boolean jboolean
byte jbyte;
char jchar;
short jshort;
int jint;
long jlong;
float jfloat;
double jdouble;
void void
*/

//引用类型(对象)
//String jstring
//object jobject
//数组,基本数据类型的数组
//byte[] jByteArray
//对象数组
//object[](String[]) jobjectArray

//C/C++访问Java的成员

//1.访问属性
//修改属性key
JNIEXPORT jstring JNICALL Java_com_dongnaoedu_jni_JniTest_accessField
(JNIEnv *env, jobject jobj){
    //jobj是t对象,JniTest.class
    jclass cls = (*env)->GetObjectClass(env, jobj);
    //jfieldID
    //属性名称,属性签名
    jfieldID fid = (*env)->GetFieldID(env, cls, "key", "Ljava/lang/String;");   

    //jason >> super jason
    //获取key属性的值
    //Get<Type>Field
    jstring jstr = (*env)->GetObjectField(env, jobj, fid);  
    printf("jstr:%#x\n",&jstr);

    //jstring -> c字符串
    //isCopy 是否复制(true代表赋值,false不复制)
    char *c_str = (*env)->GetStringUTFChars(env,jstr,JNI_FALSE);
    //拼接得到新的字符串
    char text[20] = "super ";
    strcat(text,c_str);

    //c字符串 ->jstring
    jstring new_jstr = (*env)->NewStringUTF(env, text);

    //修改key
    //Set<Type>Field
    (*env)->SetObjectField(env, jobj, fid, new_jstr);

    printf("new_jstr:%#x\n", &new_jstr);

    return new_jstr;
}

//访问静态属性
JNIEXPORT void JNICALL Java_com_dongnaoedu_jni_JniTest_accessStaticField
(JNIEnv *env, jobject jobj){
    //jclass
    jclass cls = (*env)->GetObjectClass(env, jobj);
    //jfieldID
    jfieldID fid = (*env)->GetStaticFieldID(env, cls, "count", "I");
    //GetStatic<Type>Field
    jint count = (*env)->GetStaticIntField(env, cls, fid);
    count++;
    //修改
    //SetStatic<Type>Field
    (*env)->SetStaticIntField(env,cls,fid,count);
}

//2.访问java方法
JNIEXPORT void JNICALL Java_com_dongnaoedu_jni_JniTest_accessMethod
(JNIEnv *env, jobject jobj){
    //jclass
    jclass cls = (*env)->GetObjectClass(env, jobj);
    //jmethodID
    jmethodID mid = (*env)->GetMethodID(env, cls, "genRandomInt", "(I)I");
    //调用
    //Call<Type>Method
    jint random = (*env)->CallIntMethod(env, jobj, mid, 200);
    printf("random num:%ld",random);

    //.....
}

//静态方法
JNIEXPORT void JNICALL Java_com_dongnaoedu_jni_JniTest_accessStaticMethod
(JNIEnv *env, jobject jobj){
    //jclass
    jclass cls = (*env)->GetObjectClass(env, jobj);
    //jmethodID 
    jmethodID mid = (*env)->GetStaticMethodID(env, cls, "getUUID", "()Ljava/lang/String;");
    
    //调用
    //CallStatic<Type>Method
    jstring uuid = (*env)->CallStaticObjectMethod(env, cls, mid);

    //随机文件名称 uuid.txt
    //jstring -> char*
    //isCopy JNI_FALSE,代表java和c操作的是同一个字符串
    char *uuid_str = (*env)->GetStringUTFChars(env, uuid, JNI_FALSE);
    //拼接
    char filename[100];
    sprintf(filename, "D://%s.txt",uuid_str);
    FILE *fp = fopen(filename,"w");
    fputs("i love jason", fp);
    fclose(fp);
}

//访问构造方法
//使用java.util.Date产生一个当前的时间戳
JNIEXPORT jobject JNICALL Java_com_dongnaoedu_jni_JniTest_accessConstructor
(JNIEnv *env, jobject jobj){
    jclass cls = (*env)->FindClass(env, "java/util/Date");
    //jmethodID
    jmethodID constructor_mid = (*env)->GetMethodID(env, cls, "<init>", "()V");
    //实例化一个Date对象
    jobject date_obj = (*env)->NewObject(env, cls, constructor_mid);
    //调用getTime方法
    jmethodID mid = (*env)->GetMethodID(env, cls, "getTime", "()J");
    jlong time = (*env)->CallLongMethod(env, date_obj, mid);

    printf("\ntime:%lld\n",time);

    return date_obj;
}

//调用父类的方法
JNIEXPORT void JNICALL Java_com_dongnaoedu_jni_JniTest_accessNonvirtualMethod
(JNIEnv *env, jobject jobj){
    jclass cls = (*env)->GetObjectClass(env, jobj);
    //获取man属性(对象)
    jfieldID fid = (*env)->GetFieldID(env, cls, "human", "Lcom/dongnaoedu/jni/Human;");
    //获取
    jobject human_obj = (*env)->GetObjectField(env, jobj, fid);

    //执行sayHi方法
    jclass human_cls = (*env)->FindClass(env, "com/dongnaoedu/jni/Human"); //注意:传父类的名称
    jmethodID mid = (*env)->GetMethodID(env, human_cls, "sayHi", "()V");

    //执行
    //(*env)->CallObjectMethod(env, human_obj, mid);
    //调用的父类的方法
    (*env)->CallNonvirtualObjectMethod(env, human_obj, human_cls, mid);
}

//中文问题
JNIEXPORT jstring JNICALL Java_com_dongnaoedu_jni_JniTest_chineseChars
(JNIEnv *env, jobject jobj, jstring in){
    //输出
    //char *c_str = (*env)->GetStringUTFChars(env, in, JNI_FALSE);
    //printf("%s\n",c_str);

    //c -> jstring
    char *c_str = "马蓉与宋江";
    //char c_str[] = "马蓉与宋喆";
    //jstring jstr = (*env)->NewStringUTF(env, c_str);
    //执行String(byte bytes[], String charsetName)构造方法需要的条件
    //1.jmethodID
    //2.byte数组
    //3.字符编码jstring

    jclass str_cls = (*env)->FindClass(env, "java/lang/String");
    jmethodID constructor_mid = (*env)->GetMethodID(env, str_cls, "<init>", "([BLjava/lang/String;)V");

    //jbyte -> char 
    //jbyteArray -> char[]
    jbyteArray bytes = (*env)->NewByteArray(env, strlen(c_str));
    //byte数组赋值
    //0->strlen(c_str),从头到尾
    //对等于,从c_str这个字符数组,复制到bytes这个字符数组
    (*env)->SetByteArrayRegion(env, bytes, 0, strlen(c_str), c_str);

    //字符编码jstring
    jstring charsetName = (*env)->NewStringUTF(env, "GB2312");

    //调用构造函数,返回编码之后的jstring
    return (*env)->NewObject(env,str_cls,constructor_mid,bytes,charsetName);
}

int compare(int *a,int *b){
    return (*a) - (*b);
}

//传入
JNIEXPORT void JNICALL Java_com_dongnaoedu_jni_JniTest_giveArray
(JNIEnv *env, jobject jobj, jintArray arr){
    //jintArray -> jint指针 -> c int 数组
    jint *elems = (*env)->GetIntArrayElements(env, arr, NULL);
    //printf("%#x,%#x\n", &elems, &arr);

    //数组的长度
    int len = (*env)->GetArrayLength(env, arr);
    //排序
    qsort(elems, len, sizeof(jint), compare);   

    //同步
    //mode
    //0, Java数组进行更新,并且释放C/C++数组
    //JNI_ABORT, Java数组不进行更新,但是释放C/C++数组
    //JNI_COMMIT,Java数组进行更新,不释放C/C++数组(函数执行完,数组还是会释放)
    (*env)->ReleaseIntArrayElements(env, arr, elems, JNI_COMMIT);
}

//返回数组
JNIEXPORT jintArray JNICALL Java_com_dongnaoedu_jni_JniTest_getArray(JNIEnv *env, jobject jobj, jint len){
    //创建一个指定大小的数组
    jintArray jint_arr = (*env)->NewIntArray(env, len);
    jint *elems = (*env)->GetIntArrayElements(env, jint_arr, NULL); 
    int i = 0;
    for (; i < len; i++){
        elems[i] = i;
    }

    //同步
    (*env)->ReleaseIntArrayElements(env, jint_arr, elems, 0);   

    return jint_arr;
}


//JNI 引用变量
//引用类型:局部引用和全局引用
//作用:在JNI中告知虚拟机何时回收一个JNI变量

//局部引用

JNIEXPORT jintArray JNICALL Java_com_dongnaoedu_jni_JniTest_getArray(JNIEnv *env, jobject jobj){

}

相关文章

  • JNI语法

  • Android C++开发

    语法 JNI数据类型描述符语法定义 JNI方法声明 当声明的是static方法时,传入Native的是Java类对...

  • JVM汇编语言smali

    smali语法: 有点类似于JNI的语法https://blog.csdn.net/pinksofts/artic...

  • JNI语法小结

    JNI是什么? JNI的全称就是Java Native Interface,顾名思义,就是Java和C/C++相互...

  • jni基本语法

    所有有关API可以在JNI的官网API查询 http://docs.oracle.com/javase/8/doc...

  • JNI的语法

    1.在C/C++中实现本地方法 生成C/C++头文件之后,你就需要写头文件对应的本地方法。注意:所有的本地方法的第...

  • JNI 语法总结

    先贴出对个人帮助比较大的文章,后面有空了再来填坑: JNI官方使用指南:http://hukai.me/andro...

  • jni生成方法签名

    1、native方法签名生成 编写jni经常写一些jni方法签名是很枯燥,而且经常用错,熟悉语法固然是好事,但有时...

  • jni使用语法

    概述jni(Java Native Interface)是什么? 最简单的jni使用 头文件: 实现: 注意的细节...

  • JNI教程-语法篇

    一.概述 Hello Everyone,上一篇是教大家配置了开发环境,好多同学对里面的某些代码可能还存在疑惑的,这...

网友评论

      本文标题:JNI语法

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