使用jlrs在Rust中创建Julia字符串数组并调用函数的问题
问题:使用jlrs在Rust中调用接收String数组的Julia函数
我正在用jlrs crate在Rust代码里调用Julia函数,现在需要调用一个接收Vector{String}类型参数的Julia函数,函数定义如下:
function create_temporals(ts::Vector{String}, ts_format="yyyy-mm-ddTHH:MM:SSzzzz") # ... 函数实现 end
我的Rust代码如下,但不知道怎么把Rust数据转换成Julia数组。试过用jlrs::data::managed::Array,但它需要ExtendedTarget参数,不知道怎么处理,也不清楚怎么把Rust数据传入Julia数组:
pub fn _call1<'target, 'data, T: Target<'target>>( target: T, module: &str, function: &str, data1: Value<'_, 'data> ) -> JlrsResult<ValueResult<'target, 'data, T>> { unsafe { let res = Module::main(&target) .submodule(&target, module)? .as_managed() .function(&target, function)? .as_managed() .call1(target, data1); Ok(res) } }
pub fn _temporals<T>(timestamps: &T) { let mut frame = StackFrame::new(); let mut pending = unsafe { RuntimeBuilder::new().start().expect("Could not init Julia") }; let mut julia = pending.instance(&mut frame); unsafe { let path = PathBuf::from("structures.jl"); if path.exists() { julia.include(path).expect("Could not include file"); } else { julia .include("src/Predicer/src/structures.jl") .expect("Could not include file"); } } let _x = julia.scope(|mut frame| { let timestamps: Vec<String> = vec![ "2023-06-20T10:30:00".to_string(), "2023-06-20T10:45:00".to_string(), "2023-06-20T11:00:00".to_string(), ]; // Convert the Rust vector into a Julia array let temporals = Array::new(&mut frame, (3,)); let module = "Structures"; let function = "create_temporals"; let _result_node = _call1(frame, module, function, temporals); Ok(()) }).expect("result is an error"); }
解决方案
核心要点
要将Rust的Vec<String>转换为Julia的Vector{String},需要完成两步:创建对应类型的Julia空数组,再将每个Rust字符串转换为Julia字符串并填充到数组中。ExtendedTarget本质上就是&mut Frame,直接使用闭包内的frame即可满足要求。
修正后的代码
use jlrs::prelude::*; use std::path::PathBuf; pub fn _call1<'target, 'data, T: Target<'target>>( target: T, module: &str, function: &str, data1: Value<'_, 'data> ) -> JlrsResult<ValueResult<'target, 'data, T>> { unsafe { let res = Module::main(&target) .submodule(&target, module)? .as_managed() .function(&target, function)? .as_managed() .call1(target, data1); Ok(res) } } pub fn _temporals<T>(_timestamps: &T) { let mut frame = StackFrame::new(); let mut pending = unsafe { RuntimeBuilder::new().start().expect("Could not init Julia") }; let mut julia = pending.instance(&mut frame); unsafe { let path = PathBuf::from("structures.jl"); if path.exists() { julia.include(path).expect("Could not include file"); } else { julia .include("src/Predicer/src/structures.jl") .expect("Could not include file"); } } let _x = julia.scope(|mut frame| { let timestamps: Vec<String> = vec![ "2023-06-20T10:30:00".to_string(), "2023-06-20T10:45:00".to_string(), "2023-06-20T11:00:00".to_string(), ]; // 创建Julia的String类型数组,尺寸对应Rust向量长度 let mut temporals = unsafe { Array::new::<JuliaString, _, _>(&mut frame, (timestamps.len(),)) .expect("Failed to create Julia array") }; // 遍历Rust字符串,转换为Julia字符串并填充到数组 for (idx, s) in timestamps.into_iter().enumerate() { let julia_str = unsafe { JuliaString::new(&mut frame, s) .expect("Failed to create Julia string") }; unsafe { temporals.set(&mut frame, idx as isize, julia_str) .expect("Failed to set element in array"); } } let module = "Structures"; let function = "create_temporals"; // 调用函数,注意传递frame而非消耗它 let _result_node = _call1(&mut frame, module, function, temporals.as_value()); Ok(()) }).expect("result is an error"); }
关键修正说明
- 数组创建:明确指定数组元素类型为
JuliaString(对应Julia的String),尺寸使用Rust向量的长度而非硬编码的3,提升灵活性。 - 字符串转换与填充:通过
JuliaString::new将每个RustString转换为Julia字符串,再用Array::set将元素写入数组对应位置。 - 函数调用参数:调用
_call1时传递&mut frame作为Target,并通过as_value()将数组转换为Value类型参数。
内容的提问来源于stack exchange,提问作者jeenou
相关产品推荐
相关产品推荐

