目前还没有任何方法可以从C struct 自动创建 rust 蚀类型定义.在这些情况下,有几种方法可以继续.由于不了解MySQL API,我不能确切地说您应该做什么,但这里有一些选项.
1) 将它们完全视为不透明的指针.
这是最好的情况,这取决于C API始终将 struct 作为指针,拥有自己的构造函数和析构函数,并为需要在 struct 内部访问的任何内容提供访问函数.在这些情况下,您只需定义type MYSQL = ctypes::void
,并且只将其用作不安全的指针*MYSQL
.有时,最简单的方法是编写自己的C包装,以填补空白,并使这种情况成为可能.
剩下的场景都涉及重新定义一个与C struct 相同的数据 struct .Rust试图以一种与C兼容的方式来布局其数据 struct (尽管还不总是成功),因此通常可以创建一个Rust记录或枚举,其中包含您关心的C struct 的大小、对齐方式和布局.您需要确保使用core::ctypes
中的类型,因为它们的定义与各种常见的C类型相匹配.
请注意,ctypes
模块将很快消失,取而代之的是更全面的libc兼容性模块.
2) 定义部分正确的 rust 蚀记录.
如果API提供了构造函数和析构函数,但您仍然需要访问 struct 的某些字段,那么您可以定义足够的 struct 来获取所关心的字段,而不考虑正确的大小和对齐方式.e、 g.type MSQL = { filler1: ctypes::int, ..., connector_fd: *ctypes::char }
.您可以停止在您关心的最后一个字段定义 struct ,因为您有一个C函数可以在堆上以正确的大小和对齐方式分配它.在Rust代码中,您总是使用不安全的指针来引用它:let mysql: *MYSQL = mysqlrust::create_mysql();
3) 定义尺寸和对齐正确的 rust 蚀记录,而不考虑内容.
如果没有构造函数/析构函数,或者需要将 struct 存储在堆栈上,但是有访问函数来操作 struct 的内容,那么需要定义大小和对齐方式正确的Rust记录.要做到这一点,只需添加类型为uint
的字段(总是指针大小)或uint
的元组,直到C的sizeof
和core::sys::size_of
都同意大小.如果大小不是指针大小的倍数,则用u8
填充.获得正确的对齐方式是一个更神秘的过程,但是通过使用uint
个字段,你通常会得到一个可用的对齐方式(也许——我真的不知道这个说法有多准确).
我建议增加测试,以确保 rust 迹和C的大小一致,以防止future 的破损.
3) 实际上重新定义了整个C struct .
对于大型 struct 来说,这是一个非常可怕的情况,理论上是可能的,但我认为没有人为一个大到MYSQL
的 struct 做过这件事.如果可以的话,我会避免的.最终会有一个基于叮当声的工具自动完成这项工作.
以下是一些与C struct 进行互操作的示例:
https://github.com/jdm/rust-socket/blob/master/socket.rs-这将重新定义各种套接字 struct ,为它不关心的字段添加占位符.请注意,它使用u8
作为填充,但我认为uint
更有可能产生正确的对齐.
https://github.com/erickt/rust-zmq/blob/master/zmq.rs
https://github.com/pcwalton/rust-spidermonkey-这一个演示了与一个有点复杂的API的互操作.