JNI基本操作

作者 : 开心源码 本文共4713个字,预计阅读时间需要12分钟 发布时间: 2022-05-12 共202人阅读

JNI(Java Native Interface)

Java调用C/C++,C/C++调用Java的一套API

windows下步骤

1.编写native方法
2.javah命令,生成.h头文件
3.复制.h头文件到CPP工程中
4.复制jni.h和jni_md.h文件到CPP工程中
5.实现.h头文件中公告的函数
6.生成dll文件
7.配置dll文件所在目录到环境变量
8.重启Eclipse

基本数据: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 jobjectArray

函数的实现

C的函数名称

Java_完整类名_函数名

C的函数参数

每个native函数,都至少有两个参数(JNIEnv*,jclass或者者jobject)

  • 当native方法为静态方法时:jclass 代表native方法所属类的class对象(JniTest.class)
  • 当native方法为非静态方法时:jobject 代表native方法所属的对象

访问属性

  1. GetObjectClass获得对象类
  2. GetFieldID取属性名称
  3. GetObjectField取属性值
  4. SetObjectField设置属性值

访问静态属性

  1. GetObjectClass获得对象类
  2. GetStaticFieldID取属性名称
  3. GetStaticIntField取属性值(以int类型为例)
  4. SetStaticIntField设置属性值

访问java方法

  1. GetObjectClass获得对象类
  2. GetMethodID取方法id(签名规则见下面说明)
  3. CallIntMethod调用方法

访问静态方法

  1. GetObjectClass获得对象类
  2. GetStaticMethodID取方法id(签名规则见下面说明)
  3. CallStaticObjectMethod调用方法

签名

下表为签名中,类型的对应关系。

Java类型       对应的签名boolean         Zbyte            Bchar            Cshrot           Sint             Ilong            Lfloat           Fdouble          Dvoid            VObject  L用/分割包的完整类名;  Ljava/lang/String;Array   [签名       [I       [Ljava/lang/String;

例:
void set(String str); 签名:”(Ljava/lang/String;)V”

其实除了自己对照手写之外,JDK也提供了一个很好用的生成签名的工具javap,cmd进入控制台到你要生成签名的那个类的目录下。在这里用 Order类打比如,敲入: javap -s -private Order。所有方法签名都会被输出,关于javap的少量参数可以在控制台下面输入 javap -help查看。(做coder的 毕竟还是要认几个单词的)

代码示例

java代码

package com.dm.jni;import java.util.Random;import java.util.UUID;public class JniTest {    public String key = "jason";        public static int count = 9;        public native static String getStringFromC();        public native String getString2FromC(int i);    //访问属性,返回修改之后的属性内容    public native String accessField();        public native void accessStaticField();        public native void accessMethod();        public native void accessStaticMethod();        public static void main(String[] args) {        String text = getStringFromC();        System.out.println(text);        JniTest t = new JniTest();        text = t.getString2FromC(6);        System.out.println(text);                System.out.println("key修改前:"+t.key);        t.accessField();        System.out.println("key修改后:"+t.key);                System.out.println("count修改前:"+count);        t.accessStaticField();        System.out.println("count修改后:"+count);                t.accessMethod();        t.accessStaticMethod();    }        //产生指定范围的随机数    public int genRandomInt(int max){        System.out.println("genRandomInt 执行了...");        return new Random().nextInt(max);     }        //产生UUID字符串    public static String getUUID(){        return UUID.randomUUID().toString();    }        //加载动态库    static{         System.loadLibrary("jni");    }}

C代码

#define _CRT_SECURE_NO_WARNINGS#include "com_dm_jni_JniTest.h"#include <string.h>//#include <Windows.h>//函数实现JNIEXPORT jstring JNICALL Java_com_dm_jni_JniTest_getStringFromC(JNIEnv *env, jclass jcls){    //JNIEnv 结构体指针    //env二级指针    //代表Java运行环境,调用Java中的代码    //简单的实现    //将C的字符串转为一个java字符串    return (*env)->NewStringUTF(env,"C String");}JNIEXPORT jstring JNICALL Java_com_dm_jni_JniTest_getString2FromC(JNIEnv *env, jobject jobj, jint num){    return (*env)->NewStringUTF(env,"C String2");}//C/C++访问Java的成员//1.访问属性//修改属性keyJNIEXPORT jstring JNICALL Java_com_dm_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_dm_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_dm_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_dm_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);}

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » JNI基本操作

发表回复