Java使用JNI入门For Windows7

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xxkalychen/article/details/82470183

前几天去一家公司面试,这家公司是做智能可穿戴设备的,涉及到针对硬件的操作。主要是操作蓝牙获取数据。以前没有用java去操作过硬件设备,网上也没有资料。想一想恐怕也就只能借助于C++团队,利用jni来进行技术对接了。以前虽然了解过jni,但是基本上都是在设计后台服务,比较多的是跟前端调用和后端数据库打交道,jni并没有真正用过。感觉到面试比较顺利,想着如果真的入职了,jni这方面一定会用上,所以特意研究了一下jni在Win的应用步骤。其实已经调通了,而且还在Android平台上应用NDK也过了一遍。顺便说一下,Android底层是linux平台,使用的库是编译过的.so库文件,跟linux应该是一样的。而windows编译过后是.dll动态链接库。步骤一样。差别在于编译。

Android有专用的NDK工具,编译适用于不同平台的.so库,linux下可以安装使用gcc进行编译。windows好像并不自带C++编译器。我在家里的台式机上安装了Visual Studio 2017,哗!80G,而且大部分都强行安装在系统盘。对于不是专业从事.NET开发的程序员,没有必要去安装这么大的块。所以我安装的是MingW。

安装MingW步骤很简单,在这里https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/下载MinGW-W64-install.exe。安装时记得选择x64,安装完把bin文件夹的路径添加到环境变量。因为我用的是64位的系统,所以一定要装64位的。先前我用安装器去安装,全是32位,生成的dll不能用,鼓捣了半夜。

当然我们还需要一个开发工具。高手拿个记事本都能搞定,我不行。我决定使用JetBrains的家庭成员Clion。安装步骤略过。

在配置页面,Clion会自动检测到MingW相关需要的东西,选择mingw64这个文件夹,其他各项系统会自动搜索匹配的。

现在我们打开Idea(好兄弟),创建一个普通的Java项目,创建一个包com.chris.jnidemo(我的习惯),在其中创建一个类MyMathUtils,在这个类中创建一个本地方法getSum。

package com.chris.jnidemo;

public class MyMathUtils {
    public static native int getSum(int a,int b);
}

我们创建了一个静态方法。由于C++我并不熟悉,所以就创建一个简单的逻辑,有参数有返回值j就OK了。

我们来把这个类编译为字节码文件。

G:\Workspace\Java\demo\JniDemo\src>cd com

G:\Workspace\Java\demo\JniDemo\src\com>cd chris

G:\Workspace\Java\demo\JniDemo\src\com\chris>cd jnidemo

G:\Workspace\Java\demo\JniDemo\src\com\chris\jnidemo>dir
 驱动器 G 中的卷是 WorkSpace
 卷的序列号是 0001-50E3

 G:\Workspace\Java\demo\JniDemo\src\com\chris\jnidemo 的目录

2018\09\07 周五  00:23    <DIR>          .
2018\09\07 周五  00:23    <DIR>          ..
2018\09\07 周五  00:23               112 MyMathUtils.java
               1 个文件            112 字节
               2 个目录 58,711,195,648 可用字节

G:\Workspace\Java\demo\JniDemo\src\com\chris\jnidemo>javac MyMathUtils.java

G:\Workspace\Java\demo\JniDemo\src\com\chris\jnidemo>

这时这个文件夹下面已经有了一个.class文件。接下来我们要用这个.class文件生成一个C++的头文件.h。

这里我们要用到一个命令javah,不过我们必须退回到这个类所在包的根文件夹位置,也就是src。然后执行javah。

G:\Workspace\Java\demo\JniDemo\src\com\chris\jnidemo>cd ..

G:\Workspace\Java\demo\JniDemo\src\com\chris>cd ..

G:\Workspace\Java\demo\JniDemo\src\com>cd ..

G:\Workspace\Java\demo\JniDemo\src>javah MyMathUtils
错误: 找不到 'MyMathUtils' 的类文件。

G:\Workspace\Java\demo\JniDemo\src>javah com.chris.jnidemo.MyMathUtils

G:\Workspace\Java\demo\JniDemo\src>

可以看到,必须打类的全名。javah这个命令是按照类的包名去查找这个类的,这也就是我们为什么要退到源码根文件夹下面的原因。

在我们当前的位置,会出现一个com_chris_jnidemo_MyMathUtils.h文件,这就是C++的头文件。

一般来说,Java程序员不需要自己去实现.h文件,交给C++团队就可以了。我们这里还是做一点简单的实现。

在CLion中创建一个C++ Library项目,把这个.h文件复制进去。为了看得明白,我们把这个文件名改一下,改为MyMathUtils.h。

创建一个C++的源文件MyMathUtils.c,主要是实现。把MyMathUtils.h中的方法复制进去,把.h文件的include也加进去。修改参数表,加上参数名。

#include "MyMathUtils.h"

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

.h文件里面有依据报错,jni.h找不到。

#include <jni.h>

我们去jdk文件夹下面,找到include文件夹,复制jni.h文件,到项目文件夹里面。还包括win32下面的jni_md.h。

把include的尖括号改为引号。

接着我们要修改编译列表文件CMakeLists.txt。

把MyMathUtils.c加进去,把原来的去掉,模块名也改一改。

cmake_minimum_required(VERSION 3.12)
project(CLionTest)

set(CMAKE_CXX_STANDARD 14)

add_library(MyMath SHARED MyMathUtils.c)

MyMath是我定的模块名,后面我们要在java中去加载这个名称。

看看再cmake-build-debug文件夹下面生成了libMyMath.dll动态链接库文件。

我们创建一个文件夹F:\jnidlls,来放置这些dll文件,并且在环境变量中,添加这个文件夹的位置。

这是我们回到Idea,把MyMathUtils改一下,加一个静态块,加载动态库。

package com.chris.jnidemo;

public class MyMathUtils {
    static {
        System.loadLibrary("libMyMath");
    }

    public static native int getSum(int a, int b);
}

加载的就是我们变以前设置好的那个模块名,前面系统添加了lib。

新建一个测试类。

package com.chris.jnidemo;

public class JniTest {
    public static void main(String[] args) {
        System.out.println(MyMathUtils.getSum(13579, 24680));
    }
}

看了看运行结果:

在 CentOS环境下处理JNI:https://blog.csdn.net/xxkalychen/article/details/82503427

猜你喜欢

转载自blog.csdn.net/xxkalychen/article/details/82470183
今日推荐