将C ++程序移植到Rust:reinterpret_cast,Structs和Bluetooth

时间:2017-02-23 14:46:43

标签: c++11 struct rust bluez

我有一个静态链接libbluetooth / BlueZ的C ++程序,我想把它作为练习移植到Rust。

一个特别难看的C ++代码通过read()从UNIX文件描述符中读取数据,然后通过reinterpret_cast将结果缓冲区转换为结构。不幸的是,我不知道如何在Rust中实现类似的功能。我们的想法是从le_advertising_info中捕获libbluetooth的实例。

C ++ 11代码:

std::uint8_t buf [HCI_MAX_EVENT_SIZE];
evt_le_meta_event* evt;
le_advertising_info* info;

if (read(_deviceFD, buf, sizeof (buf)) >= HCI_EVENT_HDR_SIZE) {
    evt = reinterpret_cast<evt_le_meta_event*>(buf + HCI_EVENT_HDR_SIZE + 1);
    if (evt != nullptr && evt->subevent == EVT_LE_ADVERTISING_REPORT) {
        void* offset = evt->data + 1;
        for (auto i = 0; i < evt->data [0]; i++) {
            info = reinterpret_cast<le_advertising_info*>(offset);
            if (info != nullptr) {
                if (isBeacon(*info)) {
                    writeLogEntry(*info);
                }
                offset = info->data + info->length + 2;
            }
        }
    }
}

非常感谢有关如何将此位移植到Rust(以优雅和安全的方式)的一些指示。

1 个答案:

答案 0 :(得分:4)

在Rust中,您可以使用std::mem::transmute as函数从一种类型转换为另一种类型,只要它们具有相同的大小。

在您只是从一个指针转换到另一个指针的特定情况下,甚至不需要这样做:您可以使用struct Hello { a: i32 } struct World { b: i32 } fn main() { let h = Hello { a: 42 }; let w = &h as *const Hello as *const World; let w: &World = unsafe { &*w }; println!("{}", w.b); }

unsafe

请注意,您需要unsafe关键字从指针转到引用。 Rust允许你操作指针是休闲的,但是解引用指针可能是has_many :through(如果指针指向不应该指向的地方)。

由于最后一步是“gated”,因此从引用转换为指针,或从一种指针类型转换为另一种指针类型是安全的。

与C或C ++不同,Rust中没有“严格别名”规则,因此上述内容非常安全且合规。