这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
如下图,官方的C++代码只有一个NativeLibrary.h文件,函数功能也在这个文件中,最终生成了一个jni的so文件,而实际上,应该是头文件与功能代码分离,因此本文中的头文件和C++函数的源码是分开的,先生成函数功能的so,再在java中生成jni的so,一共会有两个so文件,至于这两个so如何配置和访问,也是本文的重点之一:
官方demo的java源码如下图,是没有package信息的,而实际java工程中都会有package,由此带来的路径问题,例如头文件放哪里?编译和生成so文件时的命令行怎么处理package信息,等等官方并没有提到,而在本篇咱们的java类是有package的,与之相关的路径问题也会解决:
官方demo在运行时使用的依赖库是org.bytedeco:javacpp:1.5.5,运行时会输出以下警告信息,本篇会解决这个告警问题:
Warning: Could not load Loader: java.lang.UnsatisfiedLinkError: no jnijavacpp in java.library.path
#include "NativeLibrary.h" namespace NativeLibrary { int MyFunc::add(int a, int b) { return a + b; } }
#include<iostream> namespace NativeLibrary { class MyFunc{ public: MyFunc(){}; ~MyFunc(){}; int add(int a, int b); }; }
#include<iostream> #include"NativeLibrary.h" using namespace NativeLibrary; int main(){ MyFunc myFunc; int value = myFunc.add(1, 2); std::cout << "add value " << value << std::endl; return 0; }
g++ -std=c++11 -fPIC -shared NativeLibrary.cpp -o libMyFunc.so
g++ test.cpp -o test ./libMyFunc.so
root@docker:~/javacpp/cpp# ./test add value 3
package com.bolingcavalry.javacppdemo; import org.bytedeco.javacpp.*; import org.bytedeco.javacpp.annotation.*; @Platform(include="NativeLibrary.h",link="MyFunc") @Namespace("NativeLibrary") public class Test { public static class MyFunc extends Pointer { static { Loader.load(); } public MyFunc() { allocate(); } private native void allocate(); // to call add functions public native int add(int a, int b); } public static void main(String[] args) { MyFunc myFunc = new MyFunc(); System.out.println(myFunc .add(111,222)); } }
javac -cp javacpp-1.5.5.jar com/bolingcavalry/javacppdemo/Test.java
java \ -jar javacpp-1.5.5.jar \ com/bolingcavalry/javacppdemo/Test.java
root@docker:~/javacpp/java# java \ > -jar javacpp-1.5.5.jar \ > com/bolingcavalry/javacppdemo/Test.java Info: javac -cp javacpp-1.5.5.jar:/root/javacpp/java com/bolingcavalry/javacppdemo/Test.java Info: Generating /root/javacpp/java/jnijavacpp.cpp Info: Generating /root/javacpp/java/com/bolingcavalry/javacppdemo/jniTest.cpp Info: Compiling /root/javacpp/java/com/bolingcavalry/javacppdemo/linux-x86_64/libjniTest.so Info: g++ -I/usr/lib/jvm/jdk1.8.0_291/include -I/usr/lib/jvm/jdk1.8.0_291/include/linux /root/javacpp/java/com/bolingcavalry/javacppdemo/jniTest.cpp /root/javacpp/java/jnijavacpp.cpp -march=x86-64 -m64 -O3 -s -Wl,-rpath,$ORIGIN/ -Wl,-z,noexecstack -Wl,-Bsymbolic -Wall -fPIC -pthread -shared -o libjniTest.so -lMyFunc Info: Deleting /root/javacpp/java/com/bolingcavalry/javacppdemo/jniTest.cpp Info: Deleting /root/javacpp/java/jnijavacpp.cpp
此时的com/bolingcavalry/javacppdemo目录下新增了一个名为linux-x86_64的文件夹,里面的libjniTest.so是javacpp-1.5.5.jar生成的
您可以将/usr/lib/目录下的libMyFunc.so文件移动到linux-x86_64目录下(不移动也可以,只是个人觉得业务so文件放在/usr/lib/这种公共目录下不太合适)
将java应用运行起来:
java -cp javacpp-1.5.5.jar:. com.bolingcavalry.javacppdemo.Test
root@docker:~/javacpp/java# java -cp javacpp-1.5.5.jar:. com.bolingcavalry.javacppdemo.Test Warning: Could not load Loader: java.lang.UnsatisfiedLinkError: no jnijavacpp in java.library.path 333
root@docker:~# tree /root/javacpp /root/javacpp ├── cpp │ ├── libMyFunc.so │ ├── NativeLibrary.cpp │ ├── NativeLibrary.h │ ├── test │ └── test.cpp └── java ├── com │ └── bolingcavalry │ └── javacppdemo │ ├── linux-x86_64 │ │ ├── libjniTest.so │ │ └── libMyFunc.so │ ├── NativeLibrary.h │ ├── Test.class │ ├── Test.java │ └── Test$MyFunc.class └── javacpp-1.5.5.jar 6 directories, 12 files
root@docker:~/javacpp/java# java -cp javacpp-1.5.5.jar:. com.bolingcavalry.javacppdemo.Test Warning: Could not load Loader: java.lang.UnsatisfiedLinkError: no jnijavacpp in java.library.path 333
java -cp lib/*:. com.bolingcavalry.javacppdemo.Test
在看控制台输出如下图,这次没有告警了:
本次实战最终所有文件与目录信息如下,供您参考:
root@docker:~/javacpp# tree /root/javacpp /root/javacpp ├── cpp │ ├── libMyFunc.so │ ├── NativeLibrary.cpp │ ├── NativeLibrary.h │ ├── test │ └── test.cpp └── java ├── com │ └── bolingcavalry │ └── javacppdemo │ ├── linux-x86_64 │ │ ├── libjniTest.so │ │ └── libMyFunc.so │ ├── NativeLibrary.h │ ├── Test.class │ ├── Test.java │ └── Test$MyFunc.class ├── javacpp-1.5.5.jar └── lib ├── javacpp-1.5.5-android-arm64.jar ├── javacpp-1.5.5-android-arm.jar ├── javacpp-1.5.5-android-x86_64.jar ├── javacpp-1.5.5-android-x86.jar ├── javacpp-1.5.5-ios-arm64.jar ├── javacpp-1.5.5-ios-x86_64.jar ├── javacpp-1.5.5.jar ├── javacpp-1.5.5-linux-arm64.jar ├── javacpp-1.5.5-linux-armhf.jar ├── javacpp-1.5.5-linux-ppc64le.jar ├── javacpp-1.5.5-linux-x86_64.jar ├── javacpp-1.5.5-linux-x86.jar ├── javacpp-1.5.5-macosx-arm64.jar ├── javacpp-1.5.5-macosx-x86_64.jar ├── javacpp-1.5.5-windows-x86_64.jar ├── javacpp-1.5.5-windows-x86.jar └── javacpp-platform-1.5.5.jar 7 directories, 29 files