JNI 学习笔记(二)-- JNI访问Java中各方法

来源:互联网 发布:分红盘系统源码下载 编辑:程序博客网 时间:2024/05/16 02:43

文本同步在简书的地址:http://www.jianshu.com/p/e9c976ad7cca

1. JNI 访问 java 中的 非静态方法

package com.zeking.jni;import java.util.Random;public class JniTest02 {    public native void accessMethod();    int getRandom(int max){        return new Random().nextInt(max);    }    static{        System.loadLibrary("lsn02");    }    public static void main(String[] args) {        JniTest02 jniTest02 = new JniTest02();        jniTest02.accessMethod();    }}
#include "com_zeking_jni_JniTest02.h"/** Class:     com_zeking_jni_JniTest02* Method:    accessMethod* Signature: ()V*/// JN访问 java 中的 非静态方法JNIEXPORT void JNICALL Java_com_zeking_jni_JniTest02_accessMethod(JNIEnv * env, jobject  jobj){    jclass jclz = (*env)->GetObjectClass(env, jobj);    jmethodID jmid = (*env)->GetMethodID(env, jclz, "getRandom", "(I)I");    jint jint = (*env)->CallIntMethod(env, jobj, jmid, 200);    printf("c random: %d\n",jint);}

2. JNI 访问Java 中的静态方法

package com.zeking.jni;import java.util.Random;import java.util.UUID;public class JniTest02 {    public native void accessStaticMethod();     public static String getRandomUUId(){        return UUID.randomUUID().toString();    }    static{        System.loadLibrary("lsn02");    }    public static void main(String[] args) {        JniTest02 jniTest02 = new JniTest02();        jniTest02.accessStaticMethod();    }   }
/** Class:     com_zeking_jni_JniTest02* Method:    accessStaticMethod* Signature: ()V*/// JN访问 java 中的 非静态方法JNIEXPORT void JNICALL Java_com_zeking_jni_JniTest02_accessStaticMethod(JNIEnv *env, jobject jobj){    jclass jclz = (*env)->GetObjectClass(env, jobj);    jmethodID jmid = (*env)->GetStaticMethodID(env, jclz, "getRandomUUId", "()Ljava/lang/String;");    jstring uuid = (*env)->CallStaticIntMethod(env, jclz, jmid);    char * uuid_c = (*env)->GetStringUTFChars(env, uuid, NULL);    char filename[100];    sprintf(filename,"D://%s.txt",uuid_c);    FILE *fp = fopen(filename, "w");    fputs("I am Zeking", fp);    fclose(fp);    printf("文件写入成功\n");}

3. JNI 访问java构造方法

package com.zeking.jni;import java.util.Date;import java.util.Random;import java.util.UUID;public class JniTest02 {    static{        System.loadLibrary("lsn02");    }    public native Date accessConstructor();    public static void main(String[] args) {        JniTest02 jniTest02 = new JniTest02();        jniTest02.accessConstructor();    }   }
/** Class:     com_zeking_jni_JniTest02* Method:    accessConstructor* Signature: ()Ljava/util/Date;*/// 访问构造方法JNIEXPORT jobject JNICALL Java_com_zeking_jni_JniTest02_accessConstructor(JNIEnv * env, jobject jobj){    // 通过类的路径来从JVM 里面找到对应的类    jclass jclz = (*env)->FindClass(env, "java/util/Date");    // jmethodid     <init> 构造方法    jmethodID jmid = (*env)->GetMethodID(env, jclz, "<init>", "()V");    // 调用 newObject 实例化Date 对象,返回值是一个jobjcct    // 为什么是jobject 不是  Date,因为 在jni 里面 数据的类型对应的关系就是将所有的 引用类型全部转换为jobjct    jobject date_obj = (*env)->NewObject(env, jclz, jmid);    // 得到对应对象的方法,前提是,我们访问了相关对象的构造函数创建了这个对象    jmethodID time_mid = (*env)->GetMethodID(env, jclz, "getTime", "()J");    jlong time = (*env)->CallLongMethod(env, date_obj, time_mid);    printf("time : %lld \n", time);    return date_obj;}

4. 中文

这里写图片描述

package com.zeking.jni;import java.util.Date;import java.util.Random;import java.util.UUID;public class JniTest02 {    public native String chineseChars(String str);    static{        System.loadLibrary("lsn02");    }    public native Date accessConstructor();    public static void main(String[] args) {        JniTest02 jniTest02 = new JniTest02();        jniTest02.chineseChars("测试中文");    }   }
#include "stdafx.h"#include "com_zeking_jni_JniTest02.h"#include <Windows.h>#include <string.h>// 乱码// java使用的是// utf - 16 16bit  2个字节// JNI 里面使用的是// utf - 8   unicode  可变字节的方式   英文 1个字节    ,中文 3个字节// C C++// ascii编码, 中文 的编码方式  GB2312  编码,中文 2个 字节/** Class:     com_zeking_jni_JniTest02* Method:    chineseChars* Signature: (Ljava/lang/String;)Ljava/lang/String;*/// 中文JNIEXPORT jstring JNICALL Java_com_zeking_jni_JniTest02_chineseChars(JNIEnv * env, jobject jobj, jstring in){    // 方法一    jboolean iscp;    // char * c_str = (*env)->GetStringChars(env, in, NULL);    // JVM会重新开辟一个内存然后存储 in的值    char * c_str = (*env)->GetStringChars(env, in, &iscp);    if (iscp == JNI_TRUE) // 传&iscp 是为了获取或者得到 它的返回值,判断是否会开辟一个新的内存(这个新内存放着一样的stirng值)给 c 来使用    {        printf("is copy: JNI_TRUE\n");    }    else if (iscp == JNI_FALSE)    {        printf("is copy: JNI_FALSE\n");    }    // 得到字符串的长度    int length = (*env)->GetStringLength(env, in);    const jchar * jcstr = (*env)->GetStringChars(env, in, NULL);    // 有可能内存不够,判空    if (jcstr == NULL) {        return NULL;    }    //jchar -> char    char * rtn = (char *)malloc(sizeof(char) *2 * length + 3);    memset(rtn, 0, sizeof(char) * 2 * length + 3);    int size = 0;    // 就是当我们得到的jcstr指针变量所指的内容全部复制到 对应的指针里面来rtn(这个函数只有window环境才有)    size = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)jcstr, length, rtn, sizeof(char) * 2*length + 3, NULL, NULL);    /*if (size <= 0)    {        printf("size: 0 \n", rtn);        return NULL;    }*/    printf("string: %s\n", rtn);    if (rtn != NULL) {        free(rtn);        rtn = NULL;    }    (*env)->ReleaseStringChars(env, in, c_str);// JVM 使用。通知JVM c_str 所指的空间(这个内存是jvm另外开辟的一个内存,所以要释放)可以释放了    return NULL;    // 方法二       // String 类中构造函数,讲byte[] 转为对应编码的字符串    //public String(byte bytes[], Charset charset) {    //    this(bytes, 0, bytes.length, charset);    //}    //char *c_str = "中文中文中文";    //jclass str_cls = (*env)->FindClass(env, "java/lang/String");    //jmethodID jmid = (*env)->GetMethodID(env, str_cls, "<init>", "([BLjava/lang/String;)V");    //    ////jstring -> jbyteArray    //jbyteArray bytes = (*env)->NewByteArray(env, strlen(c_str));    //// 将Char * 赋值到 bytes    //(*env)->SetByteArrayRegion(env, bytes, 0, strlen(c_str), c_str);    //jstring charsetName = (*env)->NewStringUTF(env, "GB2312");    //return (*env)->NewObject(env, str_cls, jmid, bytes, charsetName);}
原创粉丝点击