Rust JNI开发工具jni-sys-macros的使用,实现Java本地接口的Rust宏代码自动生成

Rust JNI开发工具jni-sys-macros的使用,实现Java本地接口的Rust宏代码自动生成

安装

在项目目录中运行以下Cargo命令:

cargo add jni-sys-macros

或在Cargo.toml中添加以下行:

jni-sys-macros = "0.1.0"

使用示例

jni-sys-macros是一个用于简化Rust与Java Native Interface(JNI)交互的宏库,它可以自动生成JNI相关的Rust代码。

// 导入必要的依赖
use jni_sys_macros::jni_export;

// 使用jni_export宏自动生成JNI导出函数
#[jni_export("com.example.MyClass")]
pub extern "system" fn Java_com_example_MyClass_helloFromRust(
    env: *mut jni_sys::JNIEnv,
    _class: jni_sys::jclass,
) -> jni_sys::jstring {
    // 获取JNIEnv方法
    let env = unsafe { &*env };
    
    // 创建Java字符串
    let output = "Hello from Rust!".to_string();
    let jstring = unsafe {
        (env).NewStringUTF.unwrap()(output.as_ptr() as *const i8)
    };
    
    jstring
}

完整示例

这是一个完整的Rust JNI项目示例,展示了如何使用jni-sys-macros与Java进行交互:

// Cargo.toml依赖
[dependencies]
jni-sys = "0.3"
jni-sys-macros = "0.1"

// src/lib.rs
use jni_sys_macros::jni_export;

#[jni_export("com.example.MathOperations")]
pub extern "system" fn Java_com_example_MathOperations_addNumbers(
    _env: *mut jni_sys::JNIEnv,
    _class: jni_sys::jclass,
    a: jni_sys::jint,
    b: jni_sys::jint,
) -> jni_sys::jint {
    a + b
}

#[jni_export("com.example.MathOperations")]
pub extern "system" fn Java_com_example_MathOperations_getGreeting(
    env: *mut jni_sys::JNIEnv,
    _class: jni_sys::jclass,
) -> jni_sys::jstring {
    let env = unsafe { &*env };
    let greeting = "Hello from Rust MathOperations!".to_string();
    unsafe { (env).NewStringUTF.unwrap()(greeting.as_ptr() as *const i8) }
}

对应的Java代码示例:

package com.example;

public class MathOperations {
    // 声明native方法
    public native static int addNumbers(int a, int b);
    public native static String getGreeting();
    
    static {
        // 加载Rust生成的动态库
        System.loadLibrary("math_operations");
    }
    
    public static void main(String[] args) {
        System.out.println(getGreeting());
        System.out.println("2 + 3 = " + addNumbers(2, 3));
    }
}

构建和运行

  1. 构建Rust库为动态库:
cargo build --release
  1. 将生成的动态库放在Java的库路径中

  2. 编译并运行Java程序

特性

  • 自动生成符合JNI命名规范的函数名
  • 简化JNI类型转换
  • 提供类型安全检查
  • 减少样板代码

许可证

jni-sys-macros采用MIT或Apache-2.0双许可证。


1 回复

Rust JNI开发工具jni-sys-macros使用指南

简介

jni-sys-macros 是一个用于简化 Rust 与 Java 通过 JNI (Java Native Interface) 交互的宏库。它可以帮助开发者自动生成 JNI 相关的样板代码,使 Rust 与 Java 的互操作更加方便和安全。

安装

Cargo.toml 中添加依赖:

[dependencies]
jni-sys-macros = "0.1"
jni = "0.21"  # 通常也需要jni crate

主要功能

1. jni_fn!

自动生成符合 JNI 规范的函数声明和转换代码。

use jni_sys_macros::jni_fn;

// 自动生成JNI规范的函数名和参数转换
#[jni_fn("com.example.MyClass")]
pub fn say_hello(env: *mut jni::sys::JNIEnv, obj: jni::sys::jobject, name: jni::sys::jstring) {
    let env = unsafe { jni::JNIEnv::from_raw(env).unwrap() };
    let name: String = env.get_string(name.into()).unwrap().into();
    println!("Hello, {} from Rust!", name);
}

2. jni_impl!

为 Rust 结构体自动生成 JNI 接口实现。

use jni_sys_macros::jni_impl;

struct MyRustStruct {
    counter: i32,
}

#[jni_impl("com.example.MyJavaClass")]
impl MyRustStruct {
    #[jni_fn]
    pub fn new() -> Self {
        MyRustStruct { counter: 0 }
    }

    #[jni_fn]
    pub fn increment(&mut self) -> i32 {
        self.counter += 1;
        self.counter
    }
}

3. 异常处理

自动将 Rust 错误转换为 Java 异常:

#[jni_fn("com.example.MyClass")]
pub fn risky_operation(env: *mut jni::sys::JNIEnv, obj: jni::sys::jobject) -> jni::sys::jint {
    let result = || -> Result<i32, String> {
        // 可能失败的操作
        if some_condition {
            Ok(42)
        } else {
            Err("Something went wrong".to_string())
        }
    }();
    
    result.unwrap_or_else(|e| {
        let env = unsafe { jni::JNIEnv::极简主义风格图片,包含一个白色背景和黑色线条绘制的房子轮廓,门和窗户也是简单的黑色线条。屋顶是三角形,房子主体是长方形,门在中间,两边各有一个小方窗。没有阴影或颜色,只有干净利落的黑线。
回到顶部