https://github.com/zq2599/blog_demos
内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kubernetes、DevOPS等;
今天咱们先写C++函数,再写Java类,该Java类用JavaCPP调用C++函数;
提前小结JavaCPP开发的基本步骤如下图,稍后就按这些步骤去做:
聪明的您应该会想到:入门demo,JavaCPP官方也有啊(https://github.com/bytedeco/javacpp),难道欣宸还能比官方的好?
官方的入门demo一定是最好的,这个毋庸置疑,我这里与官方的不同之处,是添加了下面这些官方没提到的内容,更符合自己的开发习惯(官方没有这些的原因,我觉得应该是更关注JavaCPP本身,而不是一些其他的细枝末节):
官方demo在运行时使用的依赖库是org.bytedeco:javacpp:1.5.5,运行时会输出以下警告信息,本篇会解决这个告警问题:
Warning: Could not load Loader: java.lang.UnsatisfiedLinkError: no jnijavacpp in java.library.path
CSDN(不用积分):https://download.csdn.net/download/boling_cavalry/20189692
GitHub:https://raw.githubusercontent.com/zq2599/blog_download_files/master/files/javacpp-project.tar
接下来分别编写,首先是NativeLibrary.cpp,如下,仅有加法的方法:
#include "NativeLibrary.h"
namespace NativeLibrary {
int MyFunc::add(int a, int b) {
return a + b;
}
}
头文件:
#include
namespace NativeLibrary {
class MyFunc{
public:
MyFunc(){};
~MyFunc(){};
int add(int a, int b);
};
}
测试文件test.cpp,可见是验证MyFunc类的方法是否正常:
#include
#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;
}
执行以下命令,编译NativeLibrary.cpp,得到so文件libMyFunc.so:
g++ -std=c++11 -fPIC -shared NativeLibrary.cpp -o libMyFunc.so
执行以下命令,编译和链接test.cpp,得到可执行文件test:
g++ test.cpp -o test ./libMyFunc.so
运行可执行文件试试,命令是./test:
root@docker:~/javacpp/cpp# ./test
add value 3
将libMyFunc.so文件复制到/usr/lib/目录下
test的执行结果符合预期,证明so文件创建成功,记住下面两个关键信息,稍后会用到:
简单起见,咱们手写java文件,不创建maven工程
新建一个文件夹,我这边是/root/javacpp/java,java开发都在此文件夹下进行
将文件javacpp-1.5.5.jar复制到/root/javacpp/java/目录下
出于个人习惯,喜欢将java类放在packgage下,因此建好package目录,我这里是com/bolingcavalry/javacppdemo,在我这里的绝对路径就是/root/javacpp/java/com/bolingcavalry/javacppdemo
将文件NativeLibrary.h复制到com/bolingcavalry/javacppdemo目录下
在com/bolingcavalry/javacppdemo目录下新建Test.java,有几处要注意的地方稍后会提到:
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));
}
}
Test.java有以下几处需要注意:
首先是编译java文件,进入目录/root/javacpp/java,执行以下命令,即可生成class文件:
javac -cp javacpp-1.5.5.jar com/bolingcavalry/javacppdemo/Test.java
接下来要用javacpp-1.5.5.jar完成c++文件的创建和编译,生成linux下的so文件:
java <br /> -jar javacpp-1.5.5.jar <br /> com/bolingcavalry/javacppdemo/Test.java
控制台输出以下信息,表名so文件已经生成,并且清理掉了中间过程产生的临时文件:
root@docker:~/javacpp/java# java </p>
-jar javacpp-1.5.5.jar <br /> 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
控制台输出的信息如下所示,333表示调用so中的方法成功了:
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
最后,将我这里c++和java的文件夹和文件的信息详细列出来,您可以参考:
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
咱们回顾一下java应用的输出,如下所示,其中有一段告警信息:
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
上述告警信息不会影响功能,如果想消除掉,就不能只用org.bytedeco:javacpp:1.5.5这一个库,而是org.bytedeco:javacpp-platform:1.5.5,以及它的依赖库
由于本篇没有用到maven或者gradle,因此很难将org.bytedeco:javacpp-platform:1.5.5及其依赖库集齐,我这里已经将所有jar文件打包上传,您可以选择下面任意一种方式下载:
下载下来后解压,是个名为lib的文件夹,将此文件夹放在/root/javacpp/java/目录下
lib文件夹下的jar只是在运行时用到,编译时用不上,因此现在可以再次运行java应用了,命令如下:
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
至此,JavaCPP入门体验已经完成,接下来做个小结,将关键点列出来
微信搜索「程序员欣宸」,我是欣宸,期待与您一同畅游Java世界…
手机扫一扫
移动阅读更方便
你可能感兴趣的文章