Skip to content
Tool for connecting programs or libraries written in Rust with other languages
Branch: master
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
android-example fix dependecy duplication via bindgen version update Jan 16, 2019
c++_tests
jni_tests jni/java/feature: make possible return Option<ForeignClass> Mar 10, 2019
macroslib
.clang-format
.gitignore feature: automaticaly add rust_str.h and rust_vec.h to generate code Jan 23, 2018
.gitmodules
.travis.yml return back possiblity to work inside other workspaces Jan 12, 2019
LICENSE
README.md
appveyor.yml return back possiblity to work inside other workspaces Jan 12, 2019
ci_build_and_test.py
workspace.Cargo.toml return back possiblity to work inside other workspaces Jan 12, 2019

README.md

rust-swig Build status Build status License

Tool for connecting programs or libraries written in Rust with other languages. Currently implemented support for C++ and Java, but you can write support for any language of your choice. For an instruction how to integrate rust_swig with your project look here.

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);

or in C++

MyEnum v1 = ITEM1;

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

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

or in C++:

class Boo : public SomeObserver {
public:
    void onStateChanged(int, bool) override {}
};

Integration of rust_swig with your project

rust_swig is designed to be used from cargo build scripts. Just copy an appropriate code from examples crates: general java, android/java, c++ and add rust_swig as [build-dependencies] into your Cargo.toml.

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.