Я пытаюсь позвонить в библиотеку Rust от Java, и я действительно хочу использовать SWIG для создания слоя интерфейса из файла заголовка C, который я пишу (я также хочу разрешить постоянным клиентам C вызывать в мою библиотеку, следовательно, я думаю, имеет смысл поддерживать один заголовок интерфейса).Можно ли использовать Java, SWIG и Rust Together?
Я делаю это все на Windows используя Mingw и Rust (GNU ABI).
Я пойду точно, что я сделал, и результат ниже, но по существу я получаю UnsatisfiedLinkError в конце. Есть несколько вещей, которые я думаю, что может быть неправильно, но я не уверен, и я не знаю, как (или если) я могу их исправить:
- SWIG ставит номера в имени функции (вы можете увидеть это если вы редактируете файл
testlib_wrap.c
, который он производит в моем примере). - JNI documentation говорит, что мне нужно передать аргумент
-Wl,--add-stdcall-alias
при компиляции, но поскольку я строю с грузом, я не уверен, как это сделать (могу ли я передать его, если я буду строить с rustc напрямую, возможно? Я ничего не видел в man page)
Таким образом, в двух словах, мой вопрос:
Как вы звоните в Руст из Java с помощью SWIG?
Но я чувствую, что я царапаю поверхность решения, поэтому ответ может быть решением одной или обеих точек выше, поэтому здесь точно, где я до сих пор ...
Я начинал с создания новой библиотеки ржавчины с помощью Cargo:
cargo new testlib
cd testlib
Создать testlib.h
с содержимым:
void tell_me_the_answer(void);
Создать Swig входной файл (testlib.i
) со следующим содержимым :
%module testlib
%{
#include "testlib.h"
%}
%include "testlib.h"
Run SWIG, чтобы сгенерировать Java и C:
mkdir testlib
swig -outdir testlib -java -package testlib testlib.i
Создать главный класс Java (Program.java
) с содержимым:
public final class Program {
static {
System.loadLibrary("testlib");
}
public static void main(final String[] args) {
testlib.testlib.tell_me_the_answer();
}
}
скомпилировать Java:
javac Program.java testlib\testlib.java testlib\testlibJNI.java
Редактировать src\lib.rs
файл, предназначенный для ввода функции:
#[no_mangle]
pub extern "C" fn tell_me_the_answer() {
println!("The answer is...APPLES!");
}
Создать новый build.rs
файл зацепиться при составлении Swig выхода через gcc-rs библиотеку, которая содержит:
extern crate gcc;
fn main() {
gcc::Config::new()
.file("testlib_wrap.c")
.include("C:/Program Files/Java/jdk1.8.0_45/include")
.include("C:/Program Files/Java/jdk1.8.0_45/include/win32")
.compile("libtestlib.a");
}
Редактировать файл Cargo.toml
так, что он содержит:
[package]
name = "testlib"
version = "0.1.0"
build = "build.rs"
[lib]
name = "testlib"
crate-type = ["dylib"]
[build-dependencies]
gcc = "0.3"
Compile проект ржавчины:
cargo build
Запуск приложения Java:
java -Djava.library.path=target\debug Program
Получить следующую ошибку:
Exception in thread "main" java.lang.UnsatisfiedLinkError: testlib.testlibJNI.tell_me_the_answer()V
at testlib.testlibJNI.tell_me_the_answer(Native Method)
at testlib.testlib.tell_me_the_answer(testlib.java:13)
at Program.main(Program.java:6)
Я посмотрел на DLL, что груз из меня в dependency walker, и это выглядит вроде пустой (в терминах его экспорт), и единственная функция выглядит немного странно, по крайней мере, для меня, из-за s на имя и @ часть, которую я думаю, что --add-stdcall-alias
убрать правильно?
Am Я закрываю и имя в DLL, как показано в зависимости ходунки корень моей проблемы?
Если бы это было Java_testlib_testlibJNI_tell_me_the_answer
, не так ли?
Если да, то как это сделать (я отредактировал файл _wrap.c
SWIG, созданный для удаления 1s, но я не уверен, как я избавлюсь от @)?
Если нет, то в чем проблема?