从此
📄文章 #️⃣专题 🌐酷站 👨‍💻技术 📺 📱

🏠 » 📄文章 » 内容

 欢迎来访!

Java JNA、JNR比JNI更方便调用Rust库函数

🕗2024-10-19👁️0

JNA是sun公司对JNI能力的封装。咱们直接上代码。

调用系统本地库

先引入jar包:

   <!-- https://mvnrepository.com/artifact/net.java.dev.jna/jna -->
   <dependency>
     <groupId>net.java.dev.jna</groupId>
     <artifactId>jna</artifactId>
     <version>5.15.0</version>
   </dependency>

然后写java

    public static void main(String[] args) {
       jna();
   }

   public interface CLibrary extends Library {
       CLibrary INSTANCE = Native.load((Platform.isWindows() ? "msvcrt" : "c"),
               CLibrary.class);

       void printf(String format, Object... args);
   }

   private static void jna() {
       CLibrary.INSTANCE.printf("Hello, World!\n");
   }

这段代码会寻找系统的共享库,并调用库中的printf函数。

调用rust

如果上面的代码没问题,咱们继续。
新建一个rust源文件,名称随意。比如我的是 src/lib.rs

#[no_mangle]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
   a + b
}

执行命令

rustc --crate-type cdylib -o libadd.dylib src/lib.rs

你只需要更换最后一个文件参加即可。

dylib是Mac的后缀,如果是win要用dll,Linux要用so

打包完了后,把这个库文件放到java的classpath(或者直接放到target/classes/下面)。

修改java文件:

    public static void main(String[] args) {
        jna();
    }

    public interface CLibrary extends Library {
        CLibrary INSTANCE = Native.load("add", CLibrary.class);

        void printf(String format, Object... args);
        int add(int a, int b);
    }

    private static void jna() {
        CLibrary.INSTANCE.printf("Hello, World!\n");
        System.out.println(CLibrary.INSTANCE.add(1, 2));
    }

注意一下,库名不需要前缀 "lib" 和后缀。
这里增加了add方法的定义,但是没移除printf,它依然能用。

使用 JNR

通过maven引入

<!-- https://mvnrepository.com/artifact/com.github.jnr/jnr-ffi -->
<dependency>
    <groupId>com.github.jnr</groupId>
    <artifactId>jnr-ffi</artifactId>
    <version>2.2.17</version>
</dependency>

System.setProperty("java.library.path", "cp"); // 设置动态链接库搜索路径,根目录创建cp文件夹

然后在java代码中和JNA一样定义一个接口,不过不用指定父接口:

    public interface LibRst {
        int add(int a, int b);
        int puts(String s);
    }
	
LibRst libc = LibraryLoader.create(LibRst.class).load("add");
System.out.println(libc.add(2, 2));
int pr = libc.puts("put");
System.out.println(pr);

即可,比JNA还要简单。