kmp*_*kmp 5 java java-native-interface swig rust rust-cargo
我正在尝试从Java调用Rust库,我真的很想使用SWIG从我编写的C头文件生成接口层(我也希望允许常规C客户端调用我的库,因此我认为维护一个接口头很有意义)。
我正在使用Mingw和Rust(GNU ABI)在Windows上完成所有这些工作。
我将精确地做我所做的事情以及下面的结果,但是从本质上讲,我最后得到的是UnsatisfiedLinkError。我认为有几件事可能是错误的,但是我不确定,也不确定如何(或是否)可以解决这些问题:
testlib_wrap.c在我的示例中生成的文件,则可以看到此代码)。-Wl,--add-stdcall-alias在编译时传递参数,但是当我用货物建造时,我不确定该怎么做(如果我直接用rustc建造,可以传递它吗?我在手册页中看不到任何内容)简而言之,我的问题是:
您如何使用SWIG从Java调用Rust?
但是我觉得我正在摸索解决方案的表面,所以答案可能是解决上面的一个或两个问题,所以这就是我目前为止的位置...
我首先使用Cargo创建一个新的Rust库:
cargo new testlib
cd testlib
Run Code Online (Sandbox Code Playgroud)
testlib.h使用内容创建:
void tell_me_the_answer(void);
Run Code Online (Sandbox Code Playgroud)
创建testlib.i具有以下内容的Swig输入文件():
%module testlib
%{
#include "testlib.h"
%}
%include "testlib.h"
Run Code Online (Sandbox Code Playgroud)
运行swig生成一些Java和C:
mkdir testlib
swig -outdir testlib -java -package testlib testlib.i
Run Code Online (Sandbox Code Playgroud)
创建一个Program.java包含以下内容的主Java类():
public final class Program {
static {
System.loadLibrary("testlib");
}
public static void main(final String[] args) {
testlib.testlib.tell_me_the_answer();
}
}
Run Code Online (Sandbox Code Playgroud)
编译java:
javac Program.java testlib\testlib.java testlib\testlibJNI.java
Run Code Online (Sandbox Code Playgroud)
编辑src\lib.rs货运实现功能的文件:
#[no_mangle]
pub extern "C" fn tell_me_the_answer() {
println!("The answer is...APPLES!");
}
Run Code Online (Sandbox Code Playgroud)
创建一个新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");
}
Run Code Online (Sandbox Code Playgroud)
编辑Cargo.toml文件,使其包含:
[package]
name = "testlib"
version = "0.1.0"
build = "build.rs"
[lib]
name = "testlib"
crate-type = ["dylib"]
[build-dependencies]
gcc = "0.3"
Run Code Online (Sandbox Code Playgroud)
编译rust项目:
cargo build
Run Code Online (Sandbox Code Playgroud)
运行Java应用程序:
java -Djava.library.path=target\debug Program
Run Code Online (Sandbox Code Playgroud)
得到以下错误:
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)
Run Code Online (Sandbox Code Playgroud)
我看了一下货运使我成为依赖依赖行者的DLL,它看起来有点空(就其出口而言),并且至少对我来说,单个函数看起来有点怪异,这是因为名称中的1 s和我认为将删除的@部分--add-stdcall-alias正确吗?
我是否关闭了,而依赖项遍历程序中显示的DLL中的名称是我问题的根源?
如果可以,Java_testlib_testlibJNI_tell_me_the_answer那行吗?
如果是这样,我该怎么做(我编辑了_wrap.cSWIG产生的文件以删除1,但不确定如何删除@)?
如果没有,那是什么问题?
我有一个解决方案,但它并不是很漂亮,所以如果有人可以从货物中无缝实现这一点,那将是一个更好的解决方案,但批处理文件暂时对我有用。这就是我所做的......
我放弃了从 Cargo 调用 gcc,从 rust 构建了一个静态库,然后从命令行运行 gcc,将 rust 生成的 staticlib 与 SWIG 生成的代码合并在一起,并创建一个动态库,如下所示...
我改为Cargo.toml:
[package]
name = "testlib"
version = "0.1.0"
[lib]
name = "testlib"
crate-type = ["staticlib"]
Run Code Online (Sandbox Code Playgroud)
已删除build.rs
构建静态库:
cargo build
Run Code Online (Sandbox Code Playgroud)
编译 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
Run Code Online (Sandbox Code Playgroud)
现在我有一个testlib.dll在 Dependency Walker 中看起来不错的东西,当我运行它时我看到:
The answer is...APPLES!
Run Code Online (Sandbox Code Playgroud)
这是完全正确的答案。
| 归档时间: |
|
| 查看次数: |
241 次 |
| 最近记录: |