提示:文章
文章目录
- 前言
- 一、背景
- 二、
- 2.1
- 2.2
- 总结
前言
前期疑问:
本文目标:
一 背景
之前搞过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.soSRC_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)/*.orm -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文件成功
三、
3.1
总结
未完待续