【问题标题】:Send array from Julia to Rust (using "ccall")将数组从 Julia 发送到 Rust(使用“ccall”)
【发布时间】:2021-05-13 06:46:23
【问题描述】:

谁能解释一下?如何使用“ccall”函数将任何数组从 julia 发送到 rust。发送常用变量或常量没有问题。

我有Julia 代码:

A = Array{Float64,1}(undef, 2)
print("A is ",A, "\n")
ccall((:recvstruct, "target/debug/liblib"),Float64, (Ref{Array{Float64,1}}, Int32,), A, sizeof(A))

还有Rustcode

#[no_mangle]
pub extern fn recvstruct(vec: &mut Vec<f64> , len: usize){
    println!("reiceved?: {:?}", len);
    println!("reiceved?: {:?}", vec);
}

输出是:

A is [0.0, 0.0]
Hello from cargo

reiceved?: 16

还有奇怪的无尽数组:

, 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000069329110091509, 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000693291559949425, 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000693291100915405, 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000693291559949425, 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000693291100915405, 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000693291559949425, 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000693291100915563, 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000693291559949425, 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000693291100915563, 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000693291559949425, 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000693291100915563, 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000693291559949425, 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000069329110091572, 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

安装 Julia:Version 1.5.2 锈(货物):cargo 1.49.0 (d00d64df9 2020-12-05)

【问题讨论】:

  • 我对 Julia 了解不多,但您不应该将 Vec 与 ffi 一起使用。尝试使用*mut f64 看看它会带给你什么。此外,请确保两种语言之间的字节序匹配。
  • @Aiden4,我尝试在 rust 中使用 *mut f64。现在我得到了数组的引用,但没有数组的值reiceved?: 0x7f0de6114670
  • 您可以使用slice::from_raw_parts_mut 函数将指针转换为切片。请记住,len 参数是元素数,而不是字节数。或者,您可以使用ptr.read 来获取您想要的值。请注意,不要意外读取未初始化的内存或在释放后使用数组。

标签: arrays rust julia send


【解决方案1】:

朱莉娅侧

ccall(argtype1, ...) 中,将recvstruct 的第一个参数的类型声明为指向带有Ptr{T} 的内存地址的指针。

直接来自 ccall docs:

通过自动插入对 unsafe_convert(argtype, cconvert(argtype, argvalue)) 的调用,将 ccall 的每个 argvalue 转换为相应的 argtype

传递数组元素的数量而不是数组的字节大小:

a = [2.0, 3.0]
result = ccall((:recvstruct, "target/debug/liblib"), Float64, (Ptr{Float64}, UInt,), a, length(a))
println("got: $result")

锈面

recvstruct 的第一个参数声明为指向float64 数组的内存指针。

此外,使用slice::from_raw_parts 获取值的切片。

例如:

#[no_mangle]
pub extern "C" fn recvstruct(array_ptr: *const f64, len: usize) -> f64 {
    _recvstruct(unsafe {
        std::slice::from_raw_parts(array_ptr as *const f64, len)
    }, len)
}

fn _recvstruct(vec: &[f64] , len: usize) -> f64 {
    match len {
        2 => vec[0] * vec[1],
        _ => 0.0
    }
}

请注意,from_raw_parts 被标记为不安全。手册页的安全部分包含所有需要考虑的细节。

【讨论】:

  • 有没有办法将指向 Rust 中已修改数组的指针传递给 julia?我尝试使用 vec.as_ptr() 传递一个指针。在 rust 中,它看起来像 0x22402d0,而在 julia Ptr {Float64} @ 0x00000000022402d0 中,在 unsafe_wrap (Array, output, n, own = false) 之后(输出是来自 Rust 的指针),但我得到一个零数组,而不是 rust 中的修改数组。
  • 是的,有可能。查看指针传输到 Julia 的位置是否以及分配多长时间的内存。很难说可能出了什么问题,应该在 rust vec 上帮助std::mem::forget 吗?
  • 是的,你是对的。但是我使用了let mut vec_send = ManuallyDrop :: new (vec); 所以在这种情况下vec 是令人难忘的生锈。可能对某人有帮助。
猜你喜欢
  • 1970-01-01
  • 2014-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-19
  • 1970-01-01
  • 2021-05-01
相关资源
最近更新 更多