使用JNA在java中调用rust函数

冰天雪地的前进 / 2024-10-12 / 原文

JNA是sun公司对JNI能力的封装,更多信息请自行问AI。咱们直接上代码。

调用系统本地库

先引入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,它依然能用。