我正试图在铁 rust 中创建一个动态的LOGPALETTE struct .此 struct 的最后一个字段是nominally,声明为一个包含1个元素的数组,但实际上它可以是包含任意数量元素的array.我们在堆中分配 struct 时指定元素的数量.

我在C:中是这样做的:

PALETTEENTRY entry = {0};

LOGPALETTE* pLogPal = (LOGPALETTE*)malloc(
    sizeof(LOGPALETTE) + 2 * sizeof(PALETTEENTRY) // room for 2 elements
);
pLogPal->palNumEntries = 2;      // inform we have 2 elements
pLogPal->palPalEntry[0] = entry; // fill the 2 elements
pLogPal->palPalEntry[1] = entry;

// use pLogPal...

free(pLogPal);

考虑到LOGPALETTEPALETTEENTRY个声明,我如何用铁 rust 写这篇文章呢?

编辑:

我在WinSafe库here中实现了the answer.如果你想讨论它,请随时拨打the repo打开一个问题.

推荐答案

不幸的是,Rust没有对VLA提供直接支持.因此,您需要手动完成这项工作(不比C语言差,但在C语言中,您可以使用大多数语言的工具来处理指针,而在Rust中,您必须使用原始指针,不能使用引用).您还需要非常小心,不要创建引用,因为references can only be used to read the data within the size of the type they are pointing to.您也不能创建对未初始化内存的引用.

下面是这样做的一个例子:

unsafe {
    // Allocate space for 2 elements (one is already there).
    let layout = std::alloc::Layout::new::<tagLOGPALETTE>()
        .extend(std::alloc::Layout::array::<tagPALETTEENTRY>(1).unwrap())
        .unwrap()
        .0;
    let log_pal = std::alloc::alloc(layout).cast::<tagLOGPALETTE>();
    if log_pal.is_null() {
        std::alloc::handle_alloc_error(layout);
    }
    // Don't use `*` or `=`, it will create a reference!
    std::ptr::addr_of_mut!((*log_pal).palNumEntries).write(2);
    let entry = std::mem::zeroed::<tagPALETTEENTRY>();
    std::ptr::addr_of_mut!((*log_pal).palPalEntry[0])
        .add(0)
        .write(entry);
    std::ptr::addr_of_mut!((*log_pal).palPalEntry[0])
        .add(1)
        .write(entry);

    // Here, after you initialized them, you can create a slice of the entries:
    let entries = std::slice::from_raw_parts(std::ptr::addr_of!((*log_pal).palPalEntry[0]), 2);
    // But you can't create a reference to the whole type, even without accessing the entires
    // (only other fields), because you didn't initialize `palVersion`!
}

Rust相关问答推荐

为什么是!为Rust中的RwLockReadGuard和RwLockWriteGuard实现的发送特征?

阻止websocket中断的中断中断的终端(操作系统错误4)

为什么类型需要在这个代码中手动指定,在rust?

在泛型 struct 的字段声明中访问关联的Conant

rust 迹-内存管理-POP所有权-链表

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

如何将像烫手山芋一样不透明的值从一个Enum构造函数移动到下一个构造函数?

当T不执行Copy时,如何返回Arc Mutex T后面的值?

避免在Collect()上进行涡鱼类型的涂抹,以产生<;Vec<;_>;,_>;

为什么Option类型try块需要类型注释?

使用Rust WASM读取文件

具有多个键的 HashMap

结果流到 Vec 的结果:如何避免多个into_iter和collect?

Rust中如何实现一个与Sized相反的负特性(Unsized)

Rust 生命周期:这两种类型声明为不同的生命周期

判断对象是 PyDatetime 还是 Pydate 的实例?

为什么在 rust 中删除 vec 之前应该删除元素

如何在 Rust 中创建最后一个元素是可变长度数组的 struct ?

如何将 while 循环内的用户输入添加到 Rust 中的向量?

Rust 生命周期:不能在方法内重新borrow 可变字段