Java使用JNI调用C/C++(windows和android平台)

时间:2021-07-21 20:20:42

JNI的是Java Native interface(Java 本地接口)的缩写,可以通过JNI调用本地程序。

Java调用C/C++一般需要三步:
1.编写带有native方法的Java类,使用javac工具编译java类

Public JniTest
{
//声明本地方法
Public native int add(int a, int b);
}

2.使用javah来生成与native方法对应的头文件
包名和类名:
Java使用JNI调用C/C++(windows和android平台)
使用命令行工具,在src文件夹下,也就是包所存放的文件夹下执行
javah com.akuarius.jni.JniTest
执行完成后会在当前目录生成.h文件:
com_akuarius_jni_JniTest.h

内容如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_akuarius_jni_JniTest */

#ifndef _Included_com_akuarius_jni_JniTest
#define _Included_com_akuarius_jni_JniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_akuarius_jni_JniTest
* Method: add
* Signature: (II)I
*/

JNIEXPORT jint JNICALL Java_com_akuarius_jni_JniTest_add
(JNIEnv *, jobject, jint, jint);

#ifdef __cplusplus
}
#endif
#endif

3.实现相应的头文件,并编译位动态链接库(windows下.dll,linux下.so)
3.1 使用vs编译dll,在windows的java运行环境下,使用vs生成dll供java调用。
根据上一步生成的.h文件中的函数名,来用C、C++实现对应的函数。
使用vs创建一个空项目,将上述头文件添加到工程中
创建C文件:

#include"com_akuarius_jni_JniTest.h"

JNIEXPORT jint JNICALL Java_com_akuarius_jni_JniTest_add
(JNIEnv *env, jobject obj, jint a, jint b)
{
return a + b;
}

将项目的配置类型改为生成动态库:
Java使用JNI调用C/C++(windows和android平台)
然后编译。
编译可能会提示找不到jni.h文件,不用担心,只要安装了jdk,电脑中肯定是存在这个文件的。
Java使用JNI调用C/C++(windows和android平台)
Java使用JNI调用C/C++(windows和android平台)

将jni.h 和 jni_md.h拷贝到vc/include目录下,再次编译就成功了。
在release目录下会生成dll文件。
Java使用JNI调用C/C++(windows和android平台)
将该dll文件拷贝到环境变量path所包含的目录下,例如在配置jdk时添加的jdk的bin文件路径。
C:\Program Files\Java\jdk1.8.0_91\bin;

java调用本地库函数, 这里是windows下的java环境
System.loadLibrary(“JniDll”);
JniTest test = new JniTest();
Int ret Test.add(1,2);

3.2android平台使用ndk编译
Ndk是native developmet ki(本地开发工具)的缩写,能自动将so文件和java应用一起打包成apk。

3.2.1Ndk环境搭建
1.下载ndk,安装只需解压即可。
Java使用JNI调用C/C++(windows和android平台)
2.新建android工程,在android工程中新建jni文件夹
将上述的头文件和c文件拷贝进去,并且新建Android.mk用于编译生成.so文件。
Java使用JNI调用C/C++(windows和android平台)
同样会出现找不到jni.h头文件的问题
Java使用JNI调用C/C++(windows和android平台)
编辑Android.mk

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:=JniDll.cpp //注意这里是c还是cpp与文件保持一致
LOCAL_C_INCLUDES := $(JNI_H_INCLUDE)
LOCAL_MODULE := JniDll
include $(BUILD_SHARED_LIBRARY)

3.新建builder
(a)Project->Properties->Builders->New,新建一个Builder。
Java使用JNI调用C/C++(windows和android平台)
(b)在弹出的【Choose configuration type】对话框,选择【Program】,点击【OK】:
Java使用JNI调用C/C++(windows和android平台)
(c)在弹出的【Edit Configuration】对话框中,配置选项卡【Main】。
Java使用JNI调用C/C++(windows和android平台)
名称可以随意取,位置填写ndk-build.cmd的位置,工作目录填写android的项目路径。
(d)继续在这个【Edit Configuration】对话框中,配置选项卡【Refresh】
Java使用JNI调用C/C++(windows和android平台)
(e)继续在【Edit Configuration】对话框中,配置选项卡【Build options】
Java使用JNI调用C/C++(windows和android平台)
在指定资源中,选择jni目录。

执行项目->清理,就会在工程目录下生成一个obj文件夹,该文件夹中有libJniDll.so文件。
有时会没有.so文件,只有.o.d文件,需要重新指定NDK路径。
Java使用JNI调用C/C++(windows和android平台)
在程序中使用静态加载,同变量的声明在一起
再次执行项目构建即可
Java使用JNI调用C/C++(windows和android平台)

    static{
System.loadLibrary("JniDll");
}

调用

    JniTest test = new JniTest(); 
System.out.printf("%d \n", test.add(1, 2));