我想用Rust语言调用C库“mysql.h”

时间:2012-02-26 03:17:58

标签: c rust

我试图从防锈代码连接到mysql。我已尝试过这些步骤。

    1.我使用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型结构。

1 个答案:

答案 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的sizeofcore::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。