Java和C/C++ 中的基本类型的映射关系
下表中的数据为JNI基本数据类型及对应的长度
如何配置cmakelist.txt 配置编译动态库和静态库
add_library(jinInterface SHARED library.c library.h)// SHARED 表示是动态库
add_library(jinInterface STATIC library.c library.h)// STATIC 表示是静态库
ADD_LIBRARY(...)
语法:ADD_LIBRARY(libname [SHARED|STATIC] )
上面的表达式等同于:
set(LIB_SRC library.c library.h)
add_library(jinInterface SHARED ${LIB_SRC})
cmake_minimum_required(VERSION 3.14)
project(TestJni C)
set(CMAKE_C_STANDARD 11)
add_library(TestJni library.c library.h )
add_library(TheFirstLib SHARED scy_JniTest.h scy_JniTest.c)//TheFirstLib库名 scy_JniTest.h scy_JniTest.c库的具体实现
JNI 动态注册与静态注册
静态注册
1)编写java类,如JniTest.java
2)在命令行下输入 javac JniTest.java 生成JniTest.class文件
3)在 JniTest.class 目录下 通过 javah xxx.JniTest(全类名)生成 xxx_JniTest.h 头文件
4)编写xxx_JniTest.c 源文件,在这个c源文件里拷贝并实现xxx_JniTest.h 下的函数,且在其中添加jni.h头文件;
5)编写 cmakelist.txt 文件,编译生成动态/静态链接库
按照上述步骤,首先编写一个JniTest.java
package scy;
public class JniTest {
public native String nativeWorld();
public native int nativeAdd(int x, int y);
public static void main(String[] args) {
}
}
然后,用命令行编译java文件
得到头文件scy_JniTest
接着编写和头文件scy_JniTest.h同名的c文件,这里可以在Clion等IDE工具编写,并将这个头文件也copy进来
编写 cmakelist.txt 文件
编译这个C项目库后,可以在cmake-build-debug文件夹里发现生成的库文件
最后在java文件里,调用测试一下:
C文件里的返回值,都正常的输出!
动态注册
首先,编写java代码
public class DynamicJniTest {
public native void nativeDynJniTest1();
public native int nativeDyJniTest2(int x, int y);
public static void main(String[] args) {
}
}
然后就是编写C代码
#include "jni.h"
//动态注册的第一个方法
void dynamicJNIMethod1(JNIEnv *env, jobject jobj) {
printf("the first dynamic method \n");
}
//动态注册的第二个方法
jint dynamicJNIMethod2(JNIEnv *env, jobject jobj, jint x, jint y) {
printf("the second dynamic method \n");
return x+y;
}
//需要动态注册的方法数组
static const JNINativeMethod mMethods[] = {
{"nativeDynJniTest1","()V", (void *)dynamicJNIMethod1},
{"nativeDyJniTest2", "(II)I", (jint *)dynamicJNIMethod2}
};
//需要动态注册的全类名
static const char* mClassName = "scy/DynamicJniTest";
//动态注册时都会执行到这个方法中 这个实现可以当作固定范式
jint JNI_OnLoad(JavaVM *vm,void *reserved){
JNIEnv *env = NULL;
//获得JNIEnv
int r = (*vm)->GetEnv(vm,(void**)&env, JNI_VERSION_1_6);
if(r!=JNI_OK){
return -1;
}
jclass jcls = (*env)->FindClass(env,mClassName);
r = (*env)->RegisterNatives(env, jcls, mMethods, 2);
if(r!=JNI_OK){
return -1;
}
return JNI_VERSION_1_6;
}
配置CMakeLists、编译C工程等这些和静态注册一样,最后在java里调用
system.load()/system.loadLibrary() 区别
System.load
System.load 参数必须为库文件的绝对路径,可以是任意路径,例如: System.load(“C:\Documents and Settings\TestJNI.dll”); //Windows System.load("/usr/lib/TestJNI.so"); //Linux
System.loadLibrary
System.loadLibrary 参数为库文件名,不包含库文件的扩展名。 System.loadLibrary (“TestJNI”); //加载Windows下的TestJNI.dll本地库
System.loadLibrary (“TestJNI”); //加载Linux下的libTestJNI.so本地库
注意:TestJNI.dll 或 libTestJNI.so 必须是在JVM属性java.library.path所指向的路径中。loadLibary需要配置当前项目的java.library.path路径,具体办法如:https://zhidao.baidu.com/question/1241601 021778319299.html