原文链接:http://www.happycxz.com/m/?p=373
step 1 准备接口文件
先弄个java文件 Hi.java:
(我是把要测试的代码顺便也写好了,main不是必须的)
public class Hi {
static {
System.loadLibrary("Hi");
}
//声明的本地方法
public static native void Fun1(String strName);
public static native String Fun2(String strName);
public static void main(String[] args) {
Fun1("boy");
System.out.println(Fun2("girl") + ", print in JAVA.");
}
}
step 2 编译class
javac Hi.java
生成 Hi.class
step 3 生成 Hi.h 头文件
javah -classpath . Hi
生成 Hi.h 。内容如下,不需要修改:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Hi */
#ifndef _Included_Hi
#define _Included_Hi
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: Hi
* Method: Fun1
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_Hi_Fun1
(JNIEnv *, jclass, jstring);
/*
* Class: Hi
* Method: Fun2
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_Hi_Fun2
(JNIEnv *, jclass, jstring);
#ifdef __cplusplus
}
#endif
#endif
step 4 实现 Hi.c 对应功能
关于java的变量和c变量的对接使用规则,自行查百度。
#include "Hi.h"
#include <stdio.h>
//与Hi.h中函数声明相同
JNIEXPORT void JNICALL Java_Hi_Fun1 (JNIEnv * env, jclass arg, jstring instring)
{
//从instring字符串取得指向字符串UTF编码的指针
const jbyte *str = (const jbyte *)env->GetStringUTFChars( instring, JNI_FALSE );
printf("[Fun1]Hello, olami, I'm %s, print in C.\n",str);
//通知虚拟机本地代码不再需要通过str访问Java字符串。
env->ReleaseStringUTFChars( instring, (const char *)str );
return;
}
JNIEXPORT jstring JNICALL Java_Hi_Fun2 (JNIEnv * env, jclass arg, jstring instring)
{
char tmpstr[100];
const jbyte *str = (const jbyte *)env->GetStringUTFChars( instring, JNI_FALSE );
sprintf(tmpstr, "[Fun2]Hello, olami, I'm %s",str);
env->ReleaseStringUTFChars( instring, (const char *)str );
return env->NewStringUTF(tmpstr);
}
step 5 编译 Hi.c
依赖jdk中两个文件: jni.h 和 jni_md.h ;因为这两个文件在我试验机器上的两个目录,所以下述命令里需要有两个 -I 参数来指定 include 路径。
找不到这两个文件?? 可能你的机器上装的只有JRE,装一下JDK就能找到了。
g++ -I /usr/lib/jvm/java-8-openjdk-armhf/include/linux/ -I /usr/lib/jvm/java-8-openjdk-armhf/include/ -fPIC -shared -o libHi.so Hi.c
上述命令会生成 libHi.so
step 6 将libHi.so移到java.library.path中
windows环境中,会默认先找当前路径,所以不需要这一步。
linux环境下,使用libHi.so,有以下三种方式:
方式一
用java代码打印出 System.getProperty(“java.library.path”) 路径,然后把 libHi.so 拷到任意一个路径中。
方式二
添加环境变量 LD_LIBRARY_PATH ,将当前目录加到变量中:
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
方式三
直接运行时带参数,如:
java -Djava.library.path=. -cp . Hi
step 7 运行体验
使用上一步中的方式三,直接运行即可看到效果。
附全程主要操作日志:
pi@bpi-iot-ros-ai:~/jni/demo$ ll
total 16
drwxrwxr-x 2 pi pi 4096 May 23 17:29 ./
drwxrwxr-x 3 pi pi 4096 May 23 17:06 ../
-rw-rw-r-- 1 pi pi 871 May 23 17:28 Hi.c
-rw-rw-r-- 1 pi pi 348 May 23 17:28 Hi.java
pi@bpi-iot-ros-ai:~/jni/demo$ javac Hi.java
pi@bpi-iot-ros-ai:~/jni/demo$
pi@bpi-iot-ros-ai:~/jni/demo$ ll
total 20
drwxrwxr-x 2 pi pi 4096 May 23 17:30 ./
drwxrwxr-x 3 pi pi 4096 May 23 17:06 ../
-rw-rw-r-- 1 pi pi 871 May 23 17:28 Hi.c
-rw-rw-r-- 1 pi pi 785 May 23 17:30 Hi.class
-rw-rw-r-- 1 pi pi 348 May 23 17:28 Hi.java
pi@bpi-iot-ros-ai:~/jni/demo$ javah -classpath . Hi
pi@bpi-iot-ros-ai:~/jni/demo$ ll
total 24
drwxrwxr-x 2 pi pi 4096 May 23 17:30 ./
drwxrwxr-x 3 pi pi 4096 May 23 17:06 ../
-rw-rw-r-- 1 pi pi 871 May 23 17:28 Hi.c
-rw-rw-r-- 1 pi pi 785 May 23 17:30 Hi.class
-rw-rw-r-- 1 pi pi 528 May 23 17:30 Hi.h
-rw-rw-r-- 1 pi pi 348 May 23 17:28 Hi.java
pi@bpi-iot-ros-ai:~/jni/demo$ g++ -I /usr/lib/jvm/java-8-openjdk-armhf/include/linux/ -I /usr/lib/jvm/java-8-openjdk-armhf/include/ -fPIC -shared -o libHi.so Hi.c
pi@bpi-iot-ros-ai:~/jni/demo$ ll
total 36
drwxrwxr-x 2 pi pi 4096 May 23 17:30 ./
drwxrwxr-x 3 pi pi 4096 May 23 17:06 ../
-rw-rw-r-- 1 pi pi 871 May 23 17:28 Hi.c
-rw-rw-r-- 1 pi pi 785 May 23 17:30 Hi.class
-rw-rw-r-- 1 pi pi 528 May 23 17:30 Hi.h
-rw-rw-r-- 1 pi pi 348 May 23 17:28 Hi.java
-rwxrwxr-x 1 pi pi 8312 May 23 17:30 libHi.so*
pi@bpi-iot-ros-ai:~/jni/demo$ java -Djava.library.path=. -cp . Hi
[Fun1]Hello, olami, I'm boy, print in C.
[Fun2]Hello, olami, I'm girl, print in JAVA.
pi@bpi-iot-ros-ai:~/jni/demo$
pi@bpi-iot-ros-ai:~/jni/demo$