在Rust中创建与C函数指针的接口

18

如果需要,我可能没有正确描述我的问题标题,请编辑它。

我正在尝试创建一个Rust接口,以便与用C编写的LXC库进行交互。

我已经成功调用了一些简单功能,比如lxc_get_versionlxc_container_new,但我无法访问struct lxc_container块中描述的函数。

这是我的代码的一部分:

#[link(name = "lxc")]
extern {
    // LXC part
    fn lxc_get_version() -> *const c_char;
    fn lxc_container_new(name: *const c_char, configpath: *const c_char) -> LxcContainer;

    // LXC container parts
    fn is_defined(container: &LxcContainer) -> bool; 
}

这里出现了一个错误:

note: test.o: In function `LxcContainer::is_defined::heb2f16a250ac7940Vba':
test.0.rs:(.text._ZN12LxcContainer10is_defined20heb2f16a250ac7940VbaE+0x3e): undefined reference to `is_defined'

编辑:我已经将C结构体内的函数称为函数指针。我尝试过搜索类似于“Rust C函数指针”的内容,但没有找到相关信息。

1个回答

26

当你在 C 语言中看到这样的代码:

struct S {
    void (*f)(int, long)
}

这意味着结构体S包含了一个名为f的字段,它是一个指向函数的指针。这并不意味着库本身会暴露出名为f的函数。例如,下面的代码是有效的:

void some_function_1(int x, long y) { ... }

void some_function_2(int a, long b) { ... }

int main() {
    struct S s1; s1.f = some_function_1;
    struct S s2; s2.f = some_function_2;
}

这里结构体实例s1包含一个指向some_function_1的指针,而s2包含一个指向some_function_2的指针。

当你为某个C库编写Rust的FFI绑定时,通常要定义C结构体的Rust对应项。一些工具(如rust-bindgen)甚至可以自动完成此操作。在您的情况下,您需要编写类似于以下内容:

#[repr(C)]
struct LxcContainer {
    name: *mut c_char,
    configfile: *mut c_char,
    // ...
    numthreads: c_int,
    // ...
    is_defined_f: extern fn(c: *mut LxcContainer) -> bool,
    state_f: extern fn(c: *mut LxcContainer) -> *const c_char,
    // ...
}

换句话说,看起来奇怪的C函数指针类型在Rust中对应于extern fn函数指针类型。你也可以写成extern "C" fn(...) -> ...,但是因为"C"限定符是默认的,所以不是必需的。

要调用这些函数,您将需要编写类似于以下内容的代码:

impl LxcContainer {
    fn is_defined_f(&mut self) -> bool {
        unsafe {
            (self.is_defined_f)(self as *mut LxcContainer)
        }
    }
}
你需要将引用转换为原始指针,同时还需要在self.is_defined_f周围加上括号以消除方法调用和字段访问之间的歧义。
你可以在这里找到有关Rust FFI的更多信息。这里简要介绍了函数指针。

谢谢您的回答,我现在可以访问函数指针了。我已经为C表示编写了一个结构体,并为Rust表示编写了一个包装器。不幸的是,我无法调用is_defined,因为我无法将LxcContainer结构体作为*LxcContainer传递给函数。会出现解引用错误。您能否在您的回答中添加一些函数指针调用的示例?谢谢。 - bbrodriges
@bbrodriges,抱歉回复晚了。但我已经更新了我的答案,并提供了一个调用存储在结构体字段中函数的示例。 - Vladimir Matveev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接