我正在try 从rust代码连接到mysql.我试过这些步骤.

    1. I wrote c code using mysql.h, and command below.
    
     $ gcc -shared mysqlrust.c -o libmysqlrust.so  $(mysql_config --cflags) $(mysql_config --libs)   $(mysql_config --cflags)
     $ cp libmysqlrust.so /usr/local/lib/rustc/i686-unknown-linux-gnu/lib/
    
    2. I wrote Rust code, that calls libmysqlrust.so.

但我想不出使用C型 struct "MYSQL"、"MYSQL_RES"、"MYSQL_ROW"的方法.

推荐答案

目前还没有任何方法可以从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的sizeofcore::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的互操作.

Rust相关问答推荐

为什么std repeat trait绑定在impl块和关联函数之间?

如何在Bevy/Rapier3D中获得碰撞机的计算质量?

如何获取Serde struct 的默认实例

如何正确地将App handler传递给Tauri中的其他模块?

铁 rust 中的泛型:不能将`<;T作为添加>;::Output`除以`{Float}`

在Rust中克隆源自INTO_ITER()的迭代器的成本?

.在 Rust 模块标识符中

Rust 中的复合 `HashSet` 操作或如何在 Rust 中获得 `HashSet` 的显式差异/并集

Rust Option 的空显式泛型参数

Google chrome 和 Apple M1 中的计算着色器

decltype、dyn、impl traits,重构时如何声明函数的返回类型

错误:将自定义 proc_macro 与用Rust 的宝贝编写的属性一起使用时,无法在此范围内找到属性

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

如何在 nom 中构建负前瞻解析器?

我可以在不调用 .clone() 的情况下在类型转换期间重用 struct 字段吗?

在使用大型表达式时(8k 行需要一小时编译),是否可以避免 Rust 中的二次编译时间?

如何重写这个通用参数?

返回 &str 但不是 String 时,borrow 时间比预期长

为什么 u64::trailing_zeros() 在无分支工作时生成分支程序集?

返回引用的返回函数