PeterW-LWL / rust_swig

Tool for connecting programs or libraries written in Rust with other languages

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

rust-swig Build status Build status License

Getting started

Suppose you have the following Rust code:

struct Foo {
    data: i32
}

impl Foo {
    fn new(val: i32) -> Foo {
        Foo{data: val}
    }

    fn f(&self, a: i32, b: i32) -> i32 {
        self.data + a + b
    }

    fn set_field(&mut self, v: i32) {
        self.data = v;
    }
}

fn f2(a: i32) -> i32 {
    a * 2
}

and you want to write in Java something like this:

Foo foo = new Foo(5);
int res = foo.f(1, 2);
assert res == 8;

or in C++ something like this:

Foo foo(5);
int res = foo.f(1, 2);
assert(res == 8);

In order to implement it rust_swig suggests the following functionality, in Rust project you write (in Rust language):

foreigner_class!(class Foo {
    self_type Foo;
    constructor Foo::new(_: i32) -> Foo;
    method Foo::set_field(&mut self, _: i32);
    method Foo::f(&self, _: i32, _: i32) -> i32;
    static_method f2(_: i32) -> i32;
});

and that's all, as a result rust_swig generates JNI wrappers for Rust functions and Java code to call these JNI functions or generates C compatible wrappers in case of C++ and C++ code to call these C functions.

See rust_swig tests for jni for more complex examples.

Advanced

Also rust_swig support bypassing of code generation:

foreigner_class!(class Foo {
    self_type Foo;
    constructor Foo::new(_: i32) -> Foo;
    method Foo::f(&self, _: i32, _: i32) -> i32;
    static_method f2(_: i32) -> i32;
    foreigner_code "    public int javaFunc() { return 17; }\n";
    foreigner_code r#"
    public Foo[] testHandArrayReturn() { return do_testHandArrayReturn(this.mNativeObj); }
    private static native Boo[] do_testHandArrayReturn(long me);
"#;
});

after that you can implement Java_com_example_TestPathAndResult_do_1testHandArrayReturn function by your self, usefull when rust_swig can not handle something automaticaly, or you want something special.

Also you can create alias for function name:

foreigner_class!(class Foo {
    self_type Foo;
    constructor Foo::new(_: i32) -> Foo;
    method Foo::f(&self, _: i32, _: i32) -> i32; alias getF;
});

may be usefull if you want name functions in Java in camel case style, while want in Rust use snake case style.

Also you can add comments to generated code with Rust's doc comments:

foreigner_class!(
/// This is class you dream about
class Foo {
    self_type Foo;
    /// Cool constructor
    constructor Foo::new(_: i32) -> Foo;
    method Foo::f(&self, _: i32, _: i32) -> i32; alias getF;
});

Also you can "export" enum (C like enum) to foreign language:

enum MyEnum {
    Item1,
    Item2,
    Item3,
}

foreign_enum!(enum MyEnum {
  ITEM1 = MyEnum::Item1,
  ITEM2 = MyEnum::Item2,
  ITEM3 = MyEnum::Item3,
});

foreigner_class!(class Foo {
    self_type Foo;
    constructor Foo::default() -> Foo;
    method f1(&mut self, v: MyEnum);
});

after that you can write in Java:

MyEnum v1 = MyEnum.ITEM1;
Foo foo = new Foo();
foo.f1(v1);

Also you can use trait to describe callback from Rust to Java:

trait SomeTrait {
    fn on_state_changed(&self, item: i32, is_ok: bool);
}

foreign_interface!(interface SomeObserver {
    self_type SomeTrait;
    onStateChanged = SomeTrait::on_state_changed(&self, _: i32, _: bool);
});

foreigner_class!(class ClassWithCallbacks {
    self_type Foo;
    constructor Foo::default() -> Foo;
    method f1(&mut self, cb: Box<SomeTrait>);
});

and in Java you can write:

class Boo implements SomeObserver {
    public void onStateChanged(int item, boolean isOk) {}
}

Foo foo = new Foo();
Boo boo = new Boo();
foo.f1(boo);//we register callback here

About

Tool for connecting programs or libraries written in Rust with other languages

License:BSD 3-Clause "New" or "Revised" License


Languages

Language:Rust 90.5%Language:Java 3.6%Language:C++ 2.7%Language:CMake 1.6%Language:Python 1.5%Language:Shell 0.1%Language:C 0.1%