将 C++ 程序移植到 Rust:关于 reinterpret_cast、结构和蓝牙
Porting a C++ Program to Rust: Of reinterpret_cast, Structs and Bluetooth
我有一个静态链接到 libbluetooth
/BlueZ
的 C++ 程序,我想将它移植到 Rust 作为练习。
C++ 代码的一个特别丑陋的部分通过 read()
从 UNIX 文件描述符读取数据,然后通过 reinterpret_cast
将生成的缓冲区转换为结构。不幸的是,我不知道如何在 Rust 中实现类似的事情。这个想法是从 libbluetooth
.
捕获 le_advertising_info
的实例
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(以优雅和安全的方式)的一些指示。
在 Rust 中,您可以使用 unsafe
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
关键字才能从指针转到引用。 Rust 允许您随意操作指针,但是取消引用指针可能是 unsafe
(如果所述指针指向不应指向的位置)。
由于这最后一步是“门控”的,因此从引用转换为指针,或从一种指针类型转换为另一种指针类型,是安全的。
与 C 或 C++ 不同,Rust 中没有“严格的别名”规则,因此以上内容是完全安全且合规的。
我有一个静态链接到 libbluetooth
/BlueZ
的 C++ 程序,我想将它移植到 Rust 作为练习。
C++ 代码的一个特别丑陋的部分通过 read()
从 UNIX 文件描述符读取数据,然后通过 reinterpret_cast
将生成的缓冲区转换为结构。不幸的是,我不知道如何在 Rust 中实现类似的事情。这个想法是从 libbluetooth
.
le_advertising_info
的实例
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(以优雅和安全的方式)的一些指示。
在 Rust 中,您可以使用 unsafe
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
关键字才能从指针转到引用。 Rust 允许您随意操作指针,但是取消引用指针可能是 unsafe
(如果所述指针指向不应指向的位置)。
由于这最后一步是“门控”的,因此从引用转换为指针,或从一种指针类型转换为另一种指针类型,是安全的。
与 C 或 C++ 不同,Rust 中没有“严格的别名”规则,因此以上内容是完全安全且合规的。