将* mut u8转换为不带std的&[u8]

时间:2018-06-20 06:15:13

标签: rust webassembly

我正在为WebAssembly编写Rust代码,以处理来自JavaScript领域的字符串。

由于WebAssembly没有真正的字符串类型,因此我试图传递一个指向WebAssembly内存对象的指针,该对象指向UTF-8编码的字符串。

DECLARE @json NVARCHAR(MAX) = {"message":"Machine is down","machineId":"165ACE37-4E2C-4D44-9D14-F9E2CB2C2C13","machineName":"1501","ipAddress":"192.168.150.101","time":"2018-05-20T18:33:23.171"}
SELECT * FROM OPENJSON(@json) 
WITH (  message varchar(200) '$.message',
    machineId varchar(200) '$.machineId',
    machineName int '$.machineName',
    ipAddress varchar(200) '$.ipAddress',
    time datetime2(7) '$.time'
) 

它工作正常,希望我必须依靠#[no_mangle] pub extern "C" fn check(ptr: *mut u8, length: u32) -> u32 { unsafe { let buf: &[u8] = std::slice::from_raw_parts(ptr, length as usize); // do some operations on buf 0 } } 条板箱,该板条箱将最终的二进制文件膨胀到大约600KB。

有什么办法可以摆脱std但仍然能够将原始指针转换为切片?

2 个答案:

答案 0 :(得分:4)

您不能将原始指针投射到切片,因为在Rust中,切片不仅是一个指针,它是指针和大小(否则可能不安全)。

如果您不想使用std,则可以使用core crate

extern crate core;

#[no_mangle]
pub extern "C" fn check(ptr: *mut u8, length: u32) -> u32 {
    unsafe {
        let buf: &mut [u8] = core::slice::from_raw_parts_mut(ptr, length as usize);
    }
    // do some operations on buf
    0
}

core cratestd板条箱的一部分,适用于嵌入式,而无需分配所有内容。

答案 1 :(得分:3)

可以手动构造类似于切片的内容,它是由细指针和长度组成的 fat指针。然后将指向此构造的指针转换为切片的指针。

这种方法不仅不安全,而且还依赖于Rust内部(切片的内存布局),这些内部不能保证在编译器版本甚至我假设的系统之间保持稳定。如果您想确保自己的代码将来能正确运行,@ Boiethios的答案就是解决方法。但是,出于教育目的,下面的代码可能仍然很有趣:

unsafe fn make_slice<'a>(ptr: *const u8, len: usize) -> &'a [u8] {
    // place pointer address and length in contiguous memory
    let x: [usize; 2] = [ptr as usize, len];

    // cast pointer to array as pointer to slice
    let slice_ptr = &x as * const _ as *const &[u8];

    // dereference pointer to slice, so we get a slice
    *slice_ptr
}

fn main() {
    let src: Vec<u8> = vec![1, 2, 3, 4, 5, 6];
    let raw_ptr = &src[1] as *const u8;

    unsafe {
        println!("{:?}", make_slice(raw_ptr, 3));  // [2, 3, 4]
    }
}

(在playground上进行了Rust Stable 1.26.2测试)