写在最前面
Java中调用C库函数,依赖JNI,本文使用一个非常简单的例子来说明JNI开发流程,具体步骤如下:
第一步:编写Java代码
第二步:编译Java代码
第三步:生成C语言头文件
第四步:编写C代码
第五步:生成C共享库
第六步:运行Java程序
注:本文中将仅在Java代码中声明的方法称为本地方法,使用C/C++实现的函数称为本地函数。
第一步:编写Java代码
若想在Java代码中通过JNI调用C函数,首先在Java类中声明本地方法,本地方法仅在Java程序中进行声明,使用C/C++等本地语言来实现。
如下代码HelloJNI.java
1 class HelloJNI
2 {
3 // 本地方法声明
4 native void printHello();
5 native void printString(String str);
6
7 // 加载库
8 static{ System.loadLibrary("hello"); }
9
10 public static void main(String args[])
11 {
12 HelloJNI myJNI = new HelloJNI();
13
14 // 调用本地方法(实际调用的事使用C语言编写的JNI本地函数)
15 myJNI.printHello();
16 myJNI.printString("Hello World from printString fun");
17 }
18 }
在Java中,使用“native”关键字,声明本地方法,该方法与用C/C++编写的JNI本地函数相对应。
如下,不同平台下System.loadLibrary()方法加载的C运行库
操作系统平台 System.loadLibrary()方法的参数 实际加载的C运行库
Windows hello HelloJNI.dll
Linux hello HelloJNI.so
Mac hello libHelloJNI.jnilib
第二步:编译Java代码
使用Java编译器(javac),编译Java源代码,命令如下
javac HelloJNI.java
编译好HelloJNI.java后,生成HelloJNI.class
第三步:生成C语言头文件
使用javah命令生成C语言头文件,命令如下
javah HelloJNI
执行之后,生成HelloJNI.h头文件,文件内容如下
1 /* DO NOT EDIT THIS FILE - it is machine generated */
2 #include <jni.h>
3 /* Header for class HelloJNI */
4
5 #ifndef _Included_HelloJNI
6 #define _Included_HelloJNI
7 #ifdef __cplusplus
8 extern "C" {
9 #endif
10 /*
11 * Class: HelloJNI
12 * Method: printHello
13 * Signature: ()V
14 */
15 JNIEXPORT void JNICALL Java_HelloJNI_printHello
16 (JNIEnv *, jobject);
17
18 /*
19 * Class: HelloJNI
20 * Method: printString
21 * Signature: (Ljava/lang/String;)V
22 */
23 JNIEXPORT void JNICALL Java_HelloJNI_printString
24 (JNIEnv *, jobject, jstring);
25
26 #ifdef __cplusplus
27 }
28 #endif
29 #endif
第四步:编写C代码
在C函数原型文件生成后,开始编写C代码,HelloJNI.c,如下
1 #include "HelloJNI.h"
2 #include <stdio.h>
3
4 JNIEXPORT void JNICALL Java_HelloJNI_printHello(JNIEnv *env, jobject object)
5 {
6 printf("Hello World!\n");
7 return;
8 }
9
10 JNIEXPORT void JNICALL Java_HelloJNI_printString(JNIEnv *env, jobject object, jstring string)
11 {
12 // 将 Java String转换为C字符串
13 const char *str = (*env)->GetStringUTFChars(env,string,0);
14 printf("%s!\n", str);
15
16 return;
17 }
第五步:生成C共享库
mac环境下使用如下命令生成动态链接库
gcc -dynamiclib -I /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/include/ HelloJNI.c -o libHelloJNI.jnilib
后面的libHelloJNI.jnilib就是我们需要的动态链接库,但是执行这个命令的时候报了如下错误
In file included from HelloWorldImpl.c:1:
/Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/include/jni.h:45:10: fatal error:
'jni_md.h' file not found
#include "jni_md.h"
^
1 error generated.
提示jni_md.h这个文件找不到;我们执行下面的命令拷贝一份
sudo cp /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/include/darwin/jni_md.h /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk/Contents/Home/include
然后再执行生成动态库的命令即可。
第六步:运行Java程序
最后运行java程序,如下命令
java HelloJNI
即可得到如下输出结果
Hello World!
Hello World from printString fun!
总结
通过以上步骤,我们知道了Java本地方法如何通过JNI链接到C函数,以及具体实现等
最后,做个小结,梳理一下
(1)在Java类中声明本地方法
(2)使用javah命令,生成包含JNI本地函数原型的头文件
(3)实现JNI本地函数
(4)生成C共享库
(5)通过JNI,调用JNI的本地函数
---------------------
来源:CSDN
转自:https://blog.csdn.net/joeysheng/article/details/65446025