一
JNI
的书写步骤
1
)编写带有
native
声明的方法的
java
类
1
)
带有
native
关键词的
java
的类方法
(method)
,且不能在
java
中实现;
2
)在某处
load
用
C/C++
实现的库文件,例如用的此库的类中加入:
static {
System.loadLibrary("hello");
}
System.loadLibrary("hello");
}
load
一个名为
hello
的
C/C++
库,注意没有后缀,以便在不同操作系
统间兼容(夸平台性),因为各个平台的库的后缀不同;
注意,如果你的
java
的
native
动态库中,调用了其他动态库,务必现
load
被调用的动态库
3
)在
java
中调用此
native
方法时候,与其他类方法并无差异;
2
)使用
javac
命令编译所编写的
java
类
用
javac
或者其他
IDE
编译有
native
的
java
类,使之生成
.class
文件;
(一般默认即可,如要加具体参数,详见
java
的
JDK 6 Documentation
)
在这里,我们要指定
javac
的
classpath
参数,一般为:
javac -classpath */android.jar:%CLASSPATH%:./ org/soft/camera/Camera.java
*/android.jar: android.jar
的路径
%CLASSPATH%: $CLASSPATH
./:
当前路径
3
)使用
javah
命令来生成扩展名为
h
的头文件
javah -jni javaclass
命令来生成扩展名为
h
的头文件,一般为
javaclass.h
(一般默认即可,如要加具体参数,详见
java
的
JDK 6 Documentation
)
在
j
javah -classpath */android.jar:%CLASSPATH%:./ org.soft.camera.Camera
参数意义如上
4
)使用
C/C++
实现本地方法
根据步骤
3
生成的
.h
文件中对
C/C++
的函数声明,在相应的
C/C++
中实现其具
体的方法;
例如:
arm-none-linux-gnueabi-gcc -I./ -I/usr/java/jdk1.6.0_03/include -I/usr/java/jdk1.6.0_03/include/linux -fpic -c org_soft_camera_Camera.c
-I:
所用到的
.c
中的头文件
5
)将
C/C++
编写的文件生成动态连接库
在实现步骤
4
之后,在相应的系统平台生成
.dll/.so
等库文件;
arm-none-linux-gnueabi-ld -T armelf_linux_eabi.xsc -shared -o libtestjni.so cam_helper.o org_soft_camera_Camera.o
armelf_linux_eabi.xsc:
为目标平台的
“
配置
”
文件
.so:
为生成的动态库的名字,如
libtestjni.so
,在
JAVA
中
Load
的时候,格式为
System.LoadLibrary(“testjni”);
在使用库文件在
java
中
load
的时候,需注意路径问题。
二
native
的
C/C++
的接口函数声明命名规则
javah
自动生成
(略)
三
native
接口中的参数
在
javah -jni
生成的头文件中
(.h)
,在
C/C++
端,参数安排如下(按从左到右顺序):
1
)
JNIEnv* env
此为
JNI Interface pointer
Fig.3-1 JNI Interface pointer
JNI Interface pointer
指向了一个指针数组,此指针数组里包含了不同的接口函数指针;
2
)第二个参数
第二个参数基于此
native
函数是否是
static
或
nostatic
:如果为
static
的,那么
第二个参数是
native
的类的引用;如为
nostatic
的,那么为类生成的调用此函数的对象的一个引用;
3
)余下的参数
余下的参数,与
native
的函数的
java
端声明的次序一致,且如为
primitive
类型
(
int/float
等)不需要作转化,但要作对应。
Tab.3-1 Primitive Types and Native Equivalents
Java Type
|
Native Type
|
Description
|
boolean
|
jboolean
|
unsigned 8 bits
|
byte
|
jbyte
|
signed 8 bits
|
short
|
jshort
|
signed 16 bits
|
char
|
jchar
|
unsigned 16 bits
|
int
|
jint
|
signed 32 bits
|
long
|
jlong
|
signed 64 bits
|
float
|
jfloat
|
32 bits
|
double
|
jdouble
|
64 bits
|
void
|
void
|
N/A
|
而为了方便,定义了
#define JNI_FALSE 0
#define JNI_TRUE 1
与
typedef jint jsize;
如其他类形,要做转换才可以使用才可以被
C
程序识别,且
C
与
C++
的实现方式略
有不同。
具体请参见
http://java.sun.com/javase/6/docs/notes/guides/jni/spec/types.html
四
java native
中的函数(
JNI Functions
)
参照
http://java.sun.com/javase/6/docs/notes/guides/jni/spec/functions.html
五
在
JNI
中调用已有的动态库
注意,在动态库的
Load
次序,也就是在
a.so
中调用
b.so
,那么要先把
b.so
现
Load
进来
在
JNI
的
C/C++
的实现中,有可能调用到已有的动态库,在此中情况下,在实现
JNI
的
C/C++
中,需包含至少两个头文件
(.h)
:
1
)用
javah -jni
生成的头文件,此头文件中,声明了在
C/C++
实现的接口的原型;
2
)被动态库的所暴露出来的函数接口的头文件,此头文件中声明了动态库的接口函数,用于
JNI
的
C/C++
实现中调用;
3
)在
JNI
的
C/C++
实现中,注意
JNI
函数的参数与其他动态库等提供的函数间参数的互相转换;
参考
[
1
]
JDK JNI
,
http://java.sun.com/javase/6/docs/notes/guides/jni/index.html
[
2
]
JNI
入门介绍,
http://java.chinaitlab.com/JDK/36677.html
[
3
]
JNI
完全手册,
http://www.wujianrong.com/archives/2006/02/jni_1.html
[
4
]
JNI
对象在函数调用中的生命周期,
http://www.ibm.com/developerworks/cn/java/j-lo-jni/index.html
[
5
]
JNI
,
http://www.itisedu.com/phrase/200604261218435.html
[
6
]用
jni
实现
java
使用
dll
,
http://www.cnblogs.com/Aimd/archive/2006/08/18/480213.html
[
7
]
JNI Example
,