我试图从防锈代码连接到mysql。我已尝试过这些步骤。
mysql.h
编写了c代码,并在下面命令。
$ 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/
我写了Rust代码,调用libmysqlrust.so
。
醇>
但我无法找到使用C型结构的方法" MYSQL
"," MYSQL_RES
"," MYSQL_ROW
&#34 ;.
请告诉我如何使用锈蚀代码中的c型结构。
答案 0 :(得分:17)
目前还没有任何方法可以自动从C结构创建Rust类型定义。在这些情况下,有几种方法可以继续。不知道MySQL API,我不能确切地说你应该做什么,但这里有一些选择。
1)完全将它们视为不透明的指针。
这是最好的情况,并且依赖于C API总是将struct作为指针,具有自己的构造函数和析构函数,并为结构内部访问所需的任何内容提供访问器函数。在这些情况下,您只需定义type MYSQL = ctypes::void
并仅将其用作不安全指针*MYSQL
。有时最简单的方法是编写自己的C包装器来填补空白并使这种情况成为可能。
其余场景都涉及重新定义具有与C结构相同结构的Rust数据结构。 Rust尝试以与C兼容的方式布局其数据结构(虽然并不总是成功),因此通常可以使用C结构的大小,对齐和布局创建Rust记录或枚举关心。您需要确保使用core::ctypes
中的类型,因为它们被定义为匹配各种常见的C类型。
请注意,ctypes
模块将很快消失,转而使用更全面的libc兼容模块。
2)定义部分正确的Rust记录。
如果API提供构造函数和析构函数,但您仍然需要访问结构的某些字段,那么您可以定义足够的结构来获取您关注的字段,忽略正确的大小和对齐等内容。例如type MSQL = { filler1: ctypes::int, ..., connector_fd: *ctypes::char }
。您可以停止在您关心的最后一个字段定义结构,因为您有一个C函数可以在堆上使用正确的大小和对齐方式分配它。在Rust代码中,您始终使用不安全的指针引用它:let mysql: *MYSQL = mysqlrust::create_mysql();
3)定义一个正确大小和对齐的Rust记录,而不关心内容。
如果您没有构造函数/析构函数,或者需要将结构存储在堆栈上,但是您具有操作结构内容的访问器函数,那么您需要定义具有正确大小的Rust记录和对齐。要执行此操作,只需添加uint
类型的字段(总是指针大小)或uint
的元组,直到C的sizeof
和core::sys::size_of
都同意大小。如果大小不是指针大小的倍数,则填充u8
s。正确对齐是一个更神秘的过程,但通过使用uint
字段,您通常会得到一个可用的对齐(可能 - 我真的不知道该语句的准确程度)。
我建议添加测试,以便检查Rust和C是否同意尺寸,以防止未来破损。
3)实际上重新定义整个C结构。
这对于大型结构来说是一个非常可怕的情况,理论上它是可能的,但我认为没有人为MYSQL
这样大的结构做过它。如果可以,我会避免它。最终会有一个基于铿锵声的工具来自动执行此操作。
以下是与C结构互操作的一些示例:
https://github.com/jdm/rust-socket/blob/master/socket.rs - 这将重新定义各种套接字结构,为它不关心的字段添加占位符。请注意,它使用u8
进行填充,但我认为uint
更有可能产生正确的对齐。
https://github.com/erickt/rust-zmq/blob/master/zmq.rs
https://github.com/pcwalton/rust-spidermonkey - 这个演示了一个有点复杂的API。