我想调用一个Rust库,该库将为我创建一个对象increment_engine
并返回指向它的指针(或任何持久的对象)。在创建时会为该引擎提供一个参数。
稍后,我可以调用该对象的increment(a)
方法,它将把记住的参数添加到a
并返回结果。这是代码:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
public class App {
public interface MyLibrary extends Library {
MyLibrary INSTANCE = (MyLibrary) Native.loadLibrary("myjavarust", MyLibrary.class);
double addition(double a , double b);
int set_increment_engine(double parameter);
double use_increment_engine(int engine_id, double a);
}
public static void main() {
int sum = MyLibrary.INSTANCE.addition(13.0,5.0);
System.out.println(sum); // this works and prints 18 (=13+5)
engine_id = MyLibrary.INSTANCE.get_increment_engine(13.0);
double result = MyLibrary.INSTANCE.use_increment_engine(engine_id,5.0);
System.out.println(result); // this should also return 18
}
}
main()
的最后三行显示了我如何使用“增量引擎”
Rust伪代码应如下所示。
extern crate libc;
use libc::{c_double, uint32_t};
#[no_mangle]
pub extern "C" fn addition(a: f64, b: f64) -> f64 {
a + b
}
#[no_mangle]
pub extern "C" fn set_increment_engine(param: c_double) -> uint32_t {
let engine = IncrementEngine { param: param };
return_engine_id_somehow
}
#[no_mangle]
pub extern "C" fn use_increment_engine(engine_id: uint32_t, a: c_double) -> c_double {
let engine = find_engine_somehow(engine_id);
engine.increment(a)
}
struct IncrementEngine {
param: c_double,
}
impl IncrementEngine {
pub fn increment(&self, a: f64) -> f64 {
a + self.param
}
}
我已经成功测试了功能“ addition”,该功能不需要持久的“增量机器”,但是我想使用 engine 模式(显然,比起增加{{ 1}})。我研究了许多有关跨库边界传递数据的站点,关于传递结构等有很多信息,但是关于“持久指针”的信息并不多。唯一接近该解决方案的地方是in the Nomicon,其中Rust库回调了调用者,该调用者允许该对象持久化,但实际上不适用于我的用例。
该示例中的 double
是engine_id
,但大概是指向int
创建的对象的某种指针。
答案 0 :(得分:1)
This approach可以采取:
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
public class App {
public interface MyLibrary extends Library {
MyLibrary INSTANCE = (MyLibrary) Native.loadLibrary("myjavarust", MyLibrary.class);
long set_increment_engine(double parameter);
double use_increment_engine(long engine, double a);
void free_increment_engine(long engine);
}
public static void main(String[] args) {
long engine = MyLibrary.INSTANCE.set_increment_engine(13.0);
double result = MyLibrary.INSTANCE.use_increment_engine(engine, 5.0);
System.out.println(result); // returns correctly 18.0
MyLibrary.INSTANCE.free_increment_engine(engine);
}
}
使用此 lib.rs 代码:
extern crate libc;
use libc::c_double;
#[no_mangle]
pub extern "C" fn set_increment_engine(param: c_double) -> *mut IncrementEngine {
let engine = IncrementEngine { param: param };
Box::into_raw(Box::new(engine))
}
#[no_mangle]
pub extern "C" fn use_increment_engine(engine_ptr: *mut IncrementEngine, a: c_double) -> c_double {
let engine = unsafe {
assert!(!engine_ptr.is_null());
&mut *engine_ptr
};
engine.increment(a)
}
#[no_mangle]
pub extern "C" fn free_increment_engine(engine_ptr: *mut IncrementEngine) {
if engine_ptr.is_null() {
return;
}
unsafe {
Box::from_raw(engine_ptr);
}
}
pub struct IncrementEngine {
param: c_double,
}
impl IncrementEngine {
pub fn increment(&self, a: f64) -> f64 {
a + self.param
}
}
请注意,功能addition
已被删除,因为它仅用于解决问题。