1、首先,需要在类中定义静态调用本地化语言(.dll,.so)库
如下:
static {
System.loadLibrary("Jniclass");
}
2、再以native方法申明某函数调用原生库中的函数:
public static native String momo_say_Hello(String name);
3、接下来在JAVA中就可以像调用JAVA语言类中静态函数的方法调用该函数:
public static void main(String []arg)
{
momo_say_Hello("hello world!");
}
4、之后使用javac命令编译class文件
javac xxx.java
使用javah创建jni中C语言头文件,javah是对.class文件进行分析的,且不需要后缀
javah xxx
当然,创建C语言头文件也可以自己手动写,需要注意的是,jni是通过标准格式函数名来加载接口函数的
格式规范如下:
JAVA_(类名)_(JAVA中接口函数名)(参数1,参数2,……)
基本类型使用jni中的参数映射的对象,类对象使用object;见数据类型对照表
字符串较特殊,因为JAVA中没有指针,C中字符串实际上是字符指针,需要转换为jstring
数组也是比较特殊的,因为JAVA中数组属于内置类型,而C中的数组仍本质然是指针,需要转换成各种 _jXXXarray
需要注意的一点是,JAVA是面向对象编程的语言,所有内容都是类以及类的成员,JNI是搞JAVA的人搞出来的,思路当然更接近JAVA一些
既然所有函数(方法)都是类里面的对象,JNI中的导入函数当然不例外,该函数是这个类中的对象,不能被其他类直接引用
所以,接口命名规则就包含了,类名与方法名,然后最前面的JAVA表明身份是用于JNI的导出函数
很明显的可以看出,JNI是通过“_”(下划线)来区分JAVA关键字,类名关键字,函数(方法)名关键字的
那么,问题来了,如果类名中如果有个"_",如my_hello,方法名也有个"_"如momo_say_Hello( String name),
那么直接在原生语言中组合出一个JAVA_my_hello_momo_say_Hello函数
JNI会认为他是:
1、my类中的hello_momo_say_Hello函数
2、my_hello类中的momo_say_Hello函数
3、my_hello_momo类中的say_Hello函数
4、my_hello_momo_say类中的Hello函数
这样岂不是搞混了,所以,对于有"_"的函数和类,统统将"_"变成"_1"
实际上就相当于一个转译符
最终原生语言中的JNI导出函数为:JAVA_my_1hello_momo_1say_1Hello
附录,数据类型对照表:
JAVA类型 | 本地类型 | JNI中自定义类型 | 描述 |
int | long | jint/jsize | signed 32 bits |
long | _int64 | jlong | signed 64 bits |
byte | signed char | jbyte | signed 8 bits |
boolean | unsigned char | jboolean | unsigned 8 bits |
char | unsigned short | jchar | unsigned 16 bits |
short | short | jshort | signed 16 bits |
float | float | jfloat | 32 bits |
double | double | jdouble | 64 bits |
void | void | void | N/A |