编程语言
首页 > 编程语言> > JavaCPP快速入门(官方demo增强版)

JavaCPP快速入门(官方demo增强版)

作者:互联网

欢迎访问我的GitHub

https://github.com/zq2599/blog_demos

内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kubernetes、DevOPS等;

关于JavaCPP

  1. 提供一些注解,将Java代码映射为C++代码
  2. 提供一个jar,用java -jar命令可以将C++代码转为java应用可以访问的动态链接库文件;

在这里插入图片描述

本篇概览

在这里插入图片描述

与官方demo的差异

  1. 如下图,官方的C++代码只有一个NativeLibrary.h文件,函数功能也在这个文件中,最终生成了一个jni的so文件,而实际上,应该是头文件与功能代码分离,因此本文中的头文件和C++函数的源码是分开的,先生成函数功能的so,再在java中生成jni的so,一共会有两个so文件,至于这两个so如何配置和访问,也是本文的重点之一:

在这里插入图片描述

  1. 官方demo的java源码如下图,是没有package信息的,而实际java工程中都会有package,由此带来的路径问题,例如头文件放哪里?编译和生成so文件时的命令行怎么处理package信息,等等官方并没有提到,而在本篇咱们的java类是有package的,与之相关的路径问题也会解决:

在这里插入图片描述

  1. 官方demo在运行时使用的依赖库是org.bytedeco:javacpp:1.5.5,运行时会输出以下警告信息,本篇会解决这个告警问题:
Warning: Could not load Loader: java.lang.UnsatisfiedLinkError: no jnijavacpp in java.library.path

环境信息

  1. 操作系统:Ubuntu 16.04.5 LTS (server版,64位)
  2. g++:(Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
  3. JDK:1.8.0_291
  4. JavaCPP:1.5.5
  5. 操作账号:root

javacpp-1.5.5.jar文件下载

  1. CSDN(不用积分):https://download.csdn.net/download/boling_cavalry/20189395
  2. GitHub:https://raw.githubusercontent.com/zq2599/blog_download_files/master/files/javacpp-1.5.5.jar

完整源码和相关文件下载

  1. CSDN(不用积分):https://download.csdn.net/download/boling_cavalry/20189692

  2. GitHub:https://raw.githubusercontent.com/zq2599/blog_download_files/master/files/javacpp-project.tar

C++开发

  1. C++函数的源码:NativeLibrary.cpp
  2. 头文件:NativeLibrary.h
  3. 测试函数功能的文件:test.cpp(该文件仅用于测试C++函数是否正常可用,与JavcCPP无关)
#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
  1. 头文件是NativeLibrary.h
  2. so文件是libMyFunc.so

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));
    }
}
  1. Namespace注解的值是命名空间,要与前面C++代码保持一致
  2. 静态类名为MyFunc,这个要和C++中声明的类保持一致
  3. Platform注解的include属性是NativeLibrary.h,作用是指定头文件
  4. Platform注解的link属性的值是MyFunc,和so文件名libMyFunc.so相比,少了前面的lib前缀,以及so后缀,这是容易出错的地方,要千万小心,需要按照这个规则来设置link属性的值
  5. 对so中的add方法,通过native关键字做声明,然后就可以使用了

编译和运行

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
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
  1. CSDN(不用积分):https://download.csdn.net/download/boling_cavalry/20188764
  2. GitHub:https://raw.githubusercontent.com/zq2599/blog_download_files/master/files/javacpp-platform155.tar
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

关键点小结

  1. 在Java代码中,要有与C++中同名的静态类
  2. 注意Java代码中Namespace注解和C++中的namespace一致
  3. C++的头文件要和Java类放在同一个目录下
  4. 使用so库的时候,库名为libMyFunc.so,Platform注解的link参数的值就是库名去掉lib前缀和.so后缀
  5. C++函数的so文件可以放在/usr/lib目录,也可以移至linux-x86_64目录

你不孤单,欣宸原创一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 数据库+中间件系列
  6. DevOps系列

欢迎关注公众号:程序员欣宸

微信搜索「程序员欣宸」,我是欣宸,期待与您一同畅游Java世界...
https://github.com/zq2599/blog_demos

标签:1.5,java,javacpp,demo,增强版,jar,so,com,JavaCPP
来源: https://www.cnblogs.com/bolingcavalry/p/15437049.html