JNI用法

提示:文章

文章目录

前言

前期疑问:
本文目标:


一 背景

之前搞过jni,之前是强哥指导搞的,现在感觉又忘了。

今天照着帖子再搞一次。参考帖子:https://blog.csdn.net/youmingyu/article/details/53447118

二 jni实际使用

2.1 查看javac是否安装

使用java -version查看版本

C:\Users>javac -version
javac 1.8.0_262

我认为只要是装了jdk应该就有了javac。

## 2.2 windows下JAVA调用C/C++库

2.2.1 编写java代码

class HelloJNI
{
	//注意displayHelloJNI()方法的声明,它有一个关键字native,表明这个方法使用java以外的语言实现。这个方法不包括实现,因为我们要用c/c++语言实现它。
    public native int displayHelloJNI(int a,int b); //声明外部实现函数
	
    //注意System.loadLibrary("helloJNILib")这句代码,它是在静态初始化块中定义的,用来装载helloJNILib共享库,这就是我们在后面生成的helloJNILib.dll(假如在其他的操作系统可能是其他的形式,比如Linux下为helloJNILib.so)
	static {
        System.loadLibrary("win64/helloJNILib"); //导入本地库
    }

    public static void main(String[] args) {
        System.out.println(new HelloJNI().displayHelloJNI(1,2));
    }
}

2.2.2 javac生成.class文件

执行javac HelloJNI.java

代码中的注释一部分是我从网页中直接拷贝的,在执行javac HelloJNI.java指令时,会报错如下

C:\Users\\Desktop\HelloJNIPro>javac HelloJNI.java
HelloJNI.java:3: 错误: 编码GBK的不可映射字符
        //娉ㄦ剰displayHelloJNI()鏂规硶鐨勫0鏄庯紝瀹冩湁涓?涓叧閿瓧native锛岃〃鏄庤繖涓柟娉曚娇鐢╦ava浠ュ鐨勮瑷?瀹炵幇銆傝繖涓柟娉曚笉鍖呮嫭瀹炵幇锛屽洜涓烘垜浠鐢╟/c++璇█瀹炵幇瀹冦??

解决办法:在notepad中——编码——转为ANSI编码——保存

再次执行javac HelloJNI.java可以生成HelloJNI.class文件

2.2.3 javah生成.h文件

执行javah HelloJNI

2.2.4 编写C/C++本地实现代码

#include <jni.h> //导入jni头文件
#include "HelloJNI.h" //导入jni头文件
#include <stdio.h>

JNIEXPORT jint JNICALL Java_HelloJNI_displayHelloJNI(JNIEnv *env, jobject obj,jint a,jint b){
    printf("Hello JNI!\n");
    int c=a+b;
    return c;
}

2.2.4 创建vs项目

创建vs项目helloJNILib,新建项目——windows桌面——控制台应用

将上述helloJNI.cpp代码拷贝到工程中,头文件中添加helloJNI.h文件

设置引用文件路径,jni.h在JAVA_HOME/include里面

在这里插入图片描述
在这里插入图片描述

VS 添加include头文件

👉添加工程的头文件目录:

  • 当前工程 -> 右键“属性" -> “配置属性" -> “C/C++” -> “常规" -> “附加包含目录" ==> 添加上该工程的头文件存放目录即可。
  • 修好后改好之后,可能还会出现找不到头文件的提示。将平台改成电脑对应的x64

在这里插入图片描述

修改配置类型为动态库(.dll)

在这里插入图片描述
生成dll动态库文件

在这里插入图片描述

将dll文件拷贝到win64文件夹中,执行java HelloJNI指令可以成功执行
在这里插入图片描述
执行java helloJNI
运行结果
在这里插入图片描述

2.2.5 IDEA中使用dll

比想象中的简单,直接IDEA选中HelloJNI文件夹,直接运行

在这里插入图片描述
至于为什么dll文件需要放在win64文件夹下,是因为这条语句

System.loadLibrary("win64/helloJNILib"); //导入本地库

2.3 linux下JAVA调用C/C++库

windows环境是编译成.dll文件

linux环境下是编译成.so文件

将vs工程下的文件拷贝到linux服务器中,其中增加include文件夹,文件夹中增加jni.h文件和jni_md.h文件。

文件情况如图

在这里插入图片描述

编写makefile文件

CXXFLAGS = -Werror=return-type -std=c++14 -Wl,-z,relro,-z,now,-z,noexecstack -D_FORTIFY_SOURCE=2 -O2 -s -ftrapv -fPIC -fstack-protector-all -w -c -shared -o -D__STDC_LIMIT_MACROS -Dlinux -I. \

CXX = g++
C = gcc
SRC_DIR = ./
TARGET_DIR = ../build/bin/linux
TARGET_FILE = helloJNI.so

SRC_CXX=${wildcard $(SRC_DIR)/*.cpp}
SRC_CC=${wildcard $(SRC_DIR)/*.cc}

OBJ=$(SRC_CXX:.cpp=.o)
OBJ_CC=$(SRC_CC:.cc=.o)
CXXFLAGS_ALL = -Wl,-z,relro,-z,now,-z,noexecstack -D_FORTIFY_SOURCE=2 -O2 -s -ftrapv -fPIC -fstack-protector-all -static-libstdc++

all:	$(OBJ) $(OBJ_CC)
	$(CXX) $(CXXFLAGS_ALL) -shared -o $(TARGET_FILE) $(OBJ) $(OBJ_CC) $(LIBS)
	mkdir -p $(TARGET_DIR)
	cp $(TARGET_FILE) $(TARGET_DIR)/$(TARGET_FILE)
	 
clean:
	rm -f $(SRC_DIR)/*.o
	rm -f $(TARGET_FILE)
	rm -f $(TARGET_DIR)/$(TARGET_FILE)

%.o: %.cpp
	$(CXX) $(CXXFLAGS) $*.cpp -o $@


执行make,编译成功

root@0002:~/gdal_0407/helloJNI# make
g++ -Werror=return-type -std=c++14 -Wl,-z,relro,-z,now,-z,noexecstack -D_FORTIFY_SOURCE=2 -O2 -s -ftrapv -fPIC -fstack-protector-all -w -c -shared -o -D__STDC_LIMIT_MACROS -Dlinux -I. -I./include helloJNILib.cpp -o helloJNILib.o
g++ -Wl,-z,relro,-z,now,-z,noexecstack -D_FORTIFY_SOURCE=2 -O2 -s -ftrapv -fPIC -fstack-protector-all -static-libstdc++ -shared -o helloJNI.so .//helloJNILib.o
mkdir -p ../../../build/bin/linux
cp helloJNI.so ../../../build/bin/linux/helloJNI.so

make clean可以清除编译文件。

以上在linux环境下编译so文件成功

三 针对有包的java文件生成jni接口

3.1 第一点

生成jni接口的java文件可以没有main函数,比如像下面的java代码、

//testJni.java

package com.google.test.jni;

class TestJni
{
    public native boolean getCalculateData(String path);
}

如果没有package的包引入,可以直接使用javac和javah生成jni接口

这边描述的是针对引入包的情况,引入包之后使用javac是正常使用的。但是使用javah会报错:

需要将编译出的.class文件放在包对应的文件夹下,com.huawei.map.trafficlight.jni,然后再使用javah指令编译出头文件。

具体如下:

创建testJni.java文件,打开cmd,进入testJni的路径,执行

javac testJni.java

在这里插入图片描述

因为程序引入包package,创建多级文件夹com.google.test.jni,将testJni.java文件拷贝到com.google.test.jni文件夹下
执行

javah com.google.test.jni.TestJni

在这里插入图片描述
编译出的头文件在test_jni路径中
在这里插入图片描述


总结

未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值