我试图构建一对元素:

  • array: *mut T
  • array_len: usize

array旨在拥有这些数据

然而,Box::into_raw将返回*mut [T].我找不到任何有关将原始指针转换为切片的信息.它在内存中的布局是什么?如何从C中使用它?我应该改成*mut T吗?如果是,怎么做?

推荐答案

如果你只是想让一些C函数可变地borrow Vec,你可以这样做:

extern "C" {
    fn some_c_function(ptr: *mut i32, len: ffi::size_t);
}

fn safe_wrapper(a: &mut [i32]) {
    unsafe {
        some_c_function(a.as_mut_ptr(), a.len() as ffi::size_t);
    }
}

当然,C函数不应该将这个指针存储在其他地方,因为这会打破别名假设.

如果要将数据的所有权"传递"给C代码,可以执行以下操作:

use std::mem;

extern "C" {
    fn c_sink(ptr: *mut i32, len: ffi::size_t);
}

fn sink_wrapper(mut vec: Vec<i32>) {
    vec.shrink_to_fit();
    assert!(vec.len() == vec.capacity());
    let ptr = vec.as_mut_ptr();
    let len = vec.len();
    mem::forget(vec); // prevent deallocation in Rust
                      // The array is still there but no Rust object
                      // feels responsible. We only have ptr/len now
                      // to reach it.
    unsafe {
        c_sink(ptr, len as ffi::size_t);
    }
}

在这里,C函数"取得所有权",即我们期望它最终将指针和长度返回到Rust,例如,通过调用Rust函数来解除分配:

#[no_mangle]
/// This is intended for the C code to call for deallocating the
/// Rust-allocated i32 array.
unsafe extern "C" fn deallocate_rust_buffer(ptr: *mut i32, len: ffi::size_t) {
    let len = len as usize;
    drop(Vec::from_raw_parts(ptr, len, len));
}

因为Vec::from_raw_parts需要三个参数,一个指针、一个大小和一个容量,所以我们要么以某种方式跟踪容量,要么在将指针和长度传递给C函数之前使用Vec的shrink_to_fit.不过,这可能涉及重新分配.

Rust相关问答推荐

如何从Rust记录WASM堆内存使用情况?

限制未使用的泛型导致编译错误

什么时候铁 rust FFI边界上的panic 是未定义的行为?

在Rust中,如果Result是Err,运行副作用(如日志(log)记录)的惯用方法是什么

编译项目期间使用Cargo生成时出现rustc错误

为什么铁 rust S似乎有内在的易变性?

有没有可能让泛型Rust T总是堆分配的?

`*mut[T]`与`*mut T`的区别

在Rust中,Box:ed struct 与普通 struct 在删除顺序上有区别吗?

关于使用平面图功能的borrow 判断器的问题

在为第三方 struct 实现第三方特征时避免包装器的任何方法

根据掩码将 simd 通道设置为 0 的惯用方法?

在发布中包含 Rust DLL

仅当满足外部条件时如何添加到 actix web 的路由

您如何使用枚举反序列化字符串,其中任何其他值反序列化为新类型变体同时保留字符串?

如何构建包含本地依赖项的 docker 镜像?

如何在 Rust 的泛型函​​数中同时使用非拥有迭代器和消费迭代器?

在 Rust 中组合特征的不同方法是否等效?

加入动态数量的期货

令人困惑的错误消息? (解包运算符)