- JNI编程(C/C++)
- 第1节:快速上手
- 在java类中定义JNI
- 使用Java的javah工具生成.h
- 根据生成的.h编写对应的C/C++实现
- 编译为动态链接库
- 修改Java代码并测试
- 打包为独立的jar
- 第2节:实例详解(C语言版本)
- 第3节:实例详解(C++语言版本)
- 第4节:JNI数据类型
- 第5节:jstring类和jobject类的等对象数据的方法
- 第6节:多种JNI数据类型的代码实例
- 附录:代码
在类中使用native声明一个没有方法体的方法
// file location: $ProjectDir/src/pers/h01c/jni/helloJni.java
package pers.h01c.jni;
public class helloJni {
public native void helloWorld(String inputArg);
public native static String staticHelloWorld(String inputArg);
}
使用Java的javah工具生成.h
$JAVA_HOME/bin/javah -jni -classpath $ProjectDir/src/ -d $ProjectDir/jni/ pers.h01c.jni.helloJni
使用javah -help获得帮助文档
- Usage:
javah [options]
- option:
-d : Output directory # 指定生成.h的文件夹
-jni: Generate JNI-style header file # 生成jni头
-classpath/-cp : Path from which to load classes #指定从哪里寻找这个类
- :
specify with their fully qualified names #需要指定类的全名
生成出来的.h文件(路径是$ProjectDir/jni/pers_h01c_jni_helloJni.h)如下
#include根据生成的.h编写对应的C/C++实现#ifndef _Included_pers_h01c_jni_helloJni #define _Included_pers_h01c_jni_helloJni #ifdef __cplusplus extern "C" { #endif JNIEXPORT void JNICALL Java_pers_h01c_jni_helloJni_helloWorld (JNIEnv *, jobject, jstring); JNIEXPORT jstring JNICALL Java_pers_h01c_jni_helloJni_staticHelloWorld (JNIEnv *, jclass, jstring); #ifdef __cplusplus } #endif #endif
编写C/C++代码实现.h中方法逻辑,详见第2节
编译为动态链接库编译所需要include的文件有jni/下的pers_h01c_jni_helloJni.h、$JAVA_HOME/include下的jni.h、以及$JAVA_HOME/include/darwin下的jni_md.h(这里是darwin的原因是实验环境是MacOS操作系统,其他的系统的名字不一样,例如Windows可能是win32)
MacOS(darwin)编译命令
export JNI_LIB_NAME=helloJni gcc -dynamiclib -I $JAVA_HOME/include -I $JAVA_HOME/include/darwin -shared -o lib/lib$JNI_LIB_NAME.dylib jni/pers_h01c_jni_helloJni_impl.c
其他详情见第二节
另外C/C++的代码也可以使用cmake等工具编译,可以使用CLion IDE编写C/C++部分代码。
修改Java代码并测试在第一步编写的java类中静态引入动态链接库,库名字和上面的JNI_LIB_NAME一致
这里以C语言版本为例,C++版本的流程一样。
// file location: $ProjectDir/src/pers/h01c/jni/helloJni.java
package pers.h01c.jni;
public class helloJni {
static {
System.loadLibrary("helloJni"); // 注意这个库必须要在java.library.path里
}
public native void helloWorld(String inputArg);
public native static String staticHelloWorld(String inputArg);
}
如果报无法找到库的错,需要在命令行运行的时候加入VM option:
- Djava.library.path=$ProjectDir/lib/
如果是Intellj IDE环境下,则$ProjectDir的位置应该是Intellj的内置宏:$ProjectFileDir$
- Djava.library.path=$ProjectFileDir$/lib/
然后再编写对应的TestDrive类去调用这些native方法就可以了。
// file location: $ProjectDir/src/pers/h01c/jni/testDrive.java
package pers.h01c.jni;
public class testDrive {
public static void main(String[] args) {
helloJni h = new helloJni();
h.helloWorld("你好 hello jni");
System.out.println(helloJni.staticHelloWorld("static 静态你好 jni"));
}
}
打包为独立的jar
(待续,思路是先将动态链接库打包进jar,运行时动态读取然后写到临时文件,再读这个临时文件)
第2节:实例详解(C语言版本)本节针对第1节中的内例子详细说明(C),详见使用C/C++实现Java的Native方法接口(JNI)(2)实例详解(C语言版本)
第3节:实例详解(C++语言版本)本节针对第1节中的内例子详细说明(C++),详见使用C/C++实现Java的Native方法接口(JNI)(3)实例详解(C++语言版本)
第4节:JNI数据类型本节介绍了JNI中定义的部分数据类型,详见使用C/C++实现Java的Native方法接口(JNI)(4)JNI数据类型
第5节:jstring类和jobject类的等对象数据的方法本节详细描述了JNI中最常用的jstring(java.lang.String)和jobject (Obejct)的相关操作方法,详见使用C/C++实现Java的Native方法接口(JNI)(5)jstring类和jobject类的等对象数据的方法
第6节:多种JNI数据类型的代码实例本节结合前面1-5节的内容,编写了一个包含多种数据类型的实例JNI-C++代码,详见使用C/C++实现Java的Native方法接口(JNI)(6)多种JNI数据类型代码实例
附录:代码整个项目的资源打包链接:JNI_C/C++_Demo



