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

bbr*_*ges 16 c rust

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

我正在尝试为LXC库创建一个Rust接口,这是用C语言编写的.

我已成功调用简单函数lxc_get_version,lxc_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; 
}
Run Code Online (Sandbox Code Playgroud)

这是一个错误:

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

编辑:我已经管理了C结构中的函数称为函数指针.我试过谷歌像"Rust C函数指针",但没有运气.

Vla*_*eev 22

当你看到这样的东西时(在C中):

struct S {
    void (*f)(int, long)
}
Run Code Online (Sandbox Code Playgroud)

它意味着struct 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;
}
Run Code Online (Sandbox Code Playgroud)

这里struct实例s1包含一个指向some_function_1,并s2包含指向的指针some_function_2.

当您在Rust中为某些C库编写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,
    // ...
}
Run Code Online (Sandbox Code Playgroud)

也就是说,奇怪的C函数指针类型对应extern fn于Rust中的函数指针类型.你也可以写extern "C" fn(...) -> ...,但"C"限定符是默认的,所以它不是必需的.

你必须写这样的东西来调用这些函数:

impl LxcContainer {
    fn is_defined_f(&mut self) -> bool {
        unsafe {
            (self.is_defined_f)(self as *mut LxcContainer)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您需要转换对原始指针的引用,并且还需要用self.is_defined_f括号括起来以消除方法调用和字段访问之间的歧义.

你可以在这里找到关于Rust的FFI的更多信息.但是,函数指针在那里非常简单地解释.