我正在尝试从Rust调用Java库,我真的想使用SWIG从我写的C头文件生成接口层(我也想让普通的C客户端调用我的库,因此我认为维护一个接口头是有意义的。)
我使用Windows和Mingw在Rust (GNU ABI)上完成所有操作。
我将完全按照我所做的和下面的结果进行,但基本上我最后得到UnsatisfiedLinkError。我认为有些事情可能是错的,但我不确定,我不确定如何(或者如果)我可以修复它们:
testlib_wrap.c
文件,则可以看到这一点。)-Wl,--add-stdcall-alias
但是当我用货物建造时我不知道该怎么做(如果我直接用rustc构建,我可以通过它吗?也许?我在man page)简而言之,我的问题是:
如何使用SWIG从Java调用Rust ?
但我觉得我正在摸索解决方案的表面,所以答案可能正在解决上述一点或两点,所以这就是我到目前为止的确切位置......
我首先使用Cargo创建一个新的Rust库:
cargo new testlib
cd testlib
使用以下内容创建testlib.h
:
void tell_me_the_answer(void);
使用以下内容创建swig输入文件(testlib.i
):
%module testlib
%{
#include "testlib.h"
%}
%include "testlib.h"
运行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
文件,以便通过gcc-rs库来编译swig输出,其中包含:
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"
编译生锈项目:
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)
我查看了货物在dependency walker中制作的DLL,它看起来很空(就其出口而言)而且单个功能看起来有点奇怪,至少对我而言,由于名称中的 1 和 @ 部分,我认为--add-stdcall-alias
会删除吗?
我是否关闭并且依赖性walker中显示的DLL中的名称是我的问题的根源?
如果是Java_testlib_testlibJNI_tell_me_the_answer
会有效吗?
如果是这样,我该怎么做呢(我编辑了_wrap.c
文件生成的SWIG以删除1s但我不确定如何摆脱@)?
如果没有,问题是什么?
答案 0 :(得分:2)
我有一个解决方案,但它并不是真的很漂亮,所以如果有人能从货物中无缝地实现这是一个更好的解决方案,但批量文件暂时会为我做。这就是我做的......
我放弃了从货物调用gcc,从rust中构建了一个静态库,然后从命令行运行gcc以使用SWIG生成的代码生成生锈的staticlib并创建一个动态库,就像这样...
我将Cargo.toml
更改为:
[package]
name = "testlib"
version = "0.1.0"
[lib]
name = "testlib"
crate-type = ["staticlib"]
已删除build.rs
构建静态lib:
cargo build
编制了SWIG输出并将其与刚生产的货物相关联:
gcc -shared -o target\debug\testlib.dll "-LC:/Program Files (x86)/Rust stable GNU 1.9/lib/rustlib/i686-pc-windows-gnu/lib" -Ltarget\debug "-IC:/Program Files/Java/jdk1.8.0_45/include" "-IC:/Program Files/Java/jdk1.8.0_45/include/win32" testlib_wrap.c -ltestlib -lws2_32 -luserenv -lgcc_eh -lshell32 -ladvapi32 -Wl,--add-stdcall-alias
现在我有一个testlib.dll
在Dependency Walker中看起来很好,当我运行它时,我看到:
The answer is...APPLES!
这是完全正确的答案。