• JNI学习1


    实践出真知,首先是从Hello JNI开始接触

    目标文件包括:Hello.c  Hello.class  Hello.h  Hello.java  libHello.so;实现功能为在标准输出上打印Hello JNI

    操作流程是:

    • 编写Hello.java
    • 用javac Hello.java 生成 Hello.class
    • 用javah -jni Hello生成Hello.h
    • 然后编写Hello.c,使用Gcc编译共享库libHello.so
    • 最后调用java运行

    共享库的编译命令为:gcc -shared -fPIC -I /usr/local/jdk1.6.0_30/include/ -I /usr/local/jdk1.6.0_30/include/linux/ -I /usr/local/ Hello.c -o libHello.so

    运行命令为:java -Djava.library.path=. Hello

    以下是主要文件代码

    Hello.java

    View Code
    1 public class Hello{
    2     static {
    3         System.loadLibrary("Hello");
    4     }
    5     public  native void println();
    6     public static  void main(String args[]){
    7         (new Hello()).println();
    8     }
    9 }

    Hello.c

    View Code
    1 #include<stdio.h>
    2 #include"Hello.h"
    3 
    4 JNIEXPORT void JNICALL Java_Hello_println (JNIEnv *env, jobject obj) {
    5       printf("Hello JNI\n");
    6       return;
    7   }

    1、 JNI的数据类型

    基础数据类型(包括从8位、16位、32位到64位的8个(每种各两个)外加一个void,一共9个数据类型)、引用数据类型(jobject)、方法ID和域ID、值类型、UTF8字符串

    需要注意的是Java的Char是双字节(这JNI的基础类型中也一样)而C和C++中的Char是单字节。

    2、JNI接口函数命名方式

    一般JNI接口函数命名为:Java_包名_类名_方法名 (e.g. Java_basic_Hello_println)

    获取方法签名:javap -classpath <jar path> -s <class qualified name> (e.g. javap -classpath /usr/local/jdk1.6.0_30/jre/lib/rt.jar -s java.lang.String)

    3、 JNI函数与API 

    详细查看 ${JAVA_HOME}/include/jni.h,定义的 struct JNIEnv 中包括了JNI的若干接口

    4、修改Hello JNI

    如果想在打印信息里面加入一些可变信息可以通过向JNI的方法中传参处理,那么需要对Hello.java和Hello.c做如下修改

    Hello.java

    View Code
     1 package basic ;
     2 public class Hello{
     3     private static final String name="xxx";
     4     static {
     5         System.loadLibrary("Hello");
     6     }
     7     public  native void println(String name);
     8     public static  void main(String args[]){
     9         (new Hello()).println(name);
    10     }
    11 }

    Hello.c

    View Code
     1 #include<stdio.h>
     2 #include"Hello.h"
     3 
     4 JNIEXPORT void JNICALL Java_basic_Hello_println (JNIEnv *env, jobject obj, jstring str) {
     5     // get the object's class handle
     6     jclass clsstr=(*env)->FindClass(env,"java/lang/String");
     7     // create a string object in UTF-8 format
     8     jstring strencode=(*env)->NewStringUTF(env,"utf-8");
     9     // get the object's method handle, JNIenv, Object class, method name, method signature
    10     // One can get the method signature by running "javap -s <class name>"
    11     jmethodID mid=(*env)->GetMethodID(env,clsstr,"toCharArray","()[C");
    12     // invoke the object method, JNIenv, java object, method ID, parameters 
    13     jcharArray barr=(jcharArray)(*env)->CallObjectMethod(env,str,mid,strencode);
    14     jsize alen=(*env)->GetArrayLength(env,barr);
    15     
    16     jboolean tt=JNI_TRUE;// or JNI_FALSE
    17     jboolean *t=&tt;
    18     // get a point to the header of a char array, JNIenv, the array, is copy
    19     jchar* ba=(*env)->GetCharArrayElements(env,barr,t);
    20     
    21     while(*ba!='\0')
    22         printf("%c",*(ba++));
    23     ba-=alen;
    24     // release the reference of the array
    25     (*env)->ReleaseCharArrayElements(env,barr,ba,0);
    26     printf(" Hello JNI\n");
    27     return; 
    28 }   

    最后运行修改后的Hello命令:java -Djava.library.path=. basic.Hello

    运行结果:xxx Hello JNI

     5、JNI中获取方法和变量域

    大概需要如下三个步骤:

    获取对象的类,例如

    jclass clsstr=(*env)->FindClass(env,"java/lang/String");
    jclass cls=(*env)->GetObjectClass(env,myobj);
    等等

    获取类中函数/变量域的ID(GetMethodID,GetFieldID),例如

    /*
     * 使用 javap -classpath <jar path> -s <class qualified name>  获取函数签名
     */
    jmethodID mid=(*env)->GetMethodID(env,clsstr,"toCharArray","()[C");
    /*
     * JNI定义中有变量域的官方定义标签,JNI Data Structures 
     */
    jfieldID fid_msg=(*env)->GetFieldID(env,cls,"val","Z");

    调用JNI中方法对函数/变量进行访问,例如

    //变量访问
    printf("%d\n",(*env)->GetBooleanField(env,myobj,fid_msg));
    //方法调用
    jcharArray barr=(jcharArray)(*env)->CallObjectMethod(env,str,mid,strencode);

    Reference

    Java基础知识——JNI入门介绍(下)

    JNI使用规范详解

    xxx
  • 相关阅读:
    node.js结合wechaty实现微信机器人[基础篇]
    .env文件为NodeJS全局环境变量
    基于jquery实现一个提示插件
    Puppeteer实现一个超简单的自动化机器人
    Vue高仿阿里动态banner,制作组件
    css不常用属性
    Vue表单校验失败滚动到错误位置
    C# Func委托
    深入解析C# 4th 笔记(第一章)
    C# 笔记 XML基础
  • 原文地址:https://www.cnblogs.com/valder/p/3012175.html
Copyright © 2020-2023  润新知