NDK系列文章(三)JNI基础

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值