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

我正试图把一个Rust 的界面包装成LXC library,这是用C写的.

我成功地调用了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'

EDIT:我管理过C struct 中的函数称为函数指针.我试着用谷歌搜索"Rust C函数指针"之类的东西,但运气不好.

推荐答案

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

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

这意味着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;
}

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

在为某些C库编写Rust中的FFI绑定时,通常会为C struct 定义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 here中找到更多关于FFI的信息.不过,这里对函数指针进行了非常简要的解释.

Rust相关问答推荐

如何在Rust中为具有多个数据持有者的enum变体编写文档 comments ?

在actix—web中使用Redirect或NamedFile响应

为什么幻影数据不能自动推断?

在析构赋值中使用一些现有绑定

当T不执行Copy时,如何返回Arc Mutex T后面的值?

当对VEC;U8>;使用serde_json时,Base64编码是保护空间的好方法吗?

在0..1之间将U64转换为F64

在Rust 中移动原始指针的靶子安全吗

为什么`str`类型可以是任意大小(未知大小),而`string`类型的大小应该是已知的?

关于使用平面图功能的borrow 判断器的问题

将 &str 或 String 保存在变量中

使用在功能标志后面导入的类型,即使未启用功能标志

在 Rust 中,Weak 如何知道内部值何时被删除?

Rust 中函数的类型同义词

如何在 Rust Polars 中可靠地连接 LazyFrames

如何获得对数组子集的工作可变引用?

如何在 Rust 中编写修改 struct 的函数

相交着色器从 SSBO 中读取零

为什么这里需要类型注解?

如何在 Rust 中使用特征标志来捕获多行代码?