在Rust中创建C函数指针的接口
我可能没有正确描述我的问题标题,如果需要请编辑它 我试图用C语言编写一个生锈的界面 我成功地调用了一些简单函数,如在Rust中创建C函数指针的接口,c,rust,C,Rust,我可能没有正确描述我的问题标题,如果需要请编辑它 我试图用C语言编写一个生锈的界面 我成功地调用了一些简单函数,如lxc\u get\u version或lxc\u container\u new,但我无法访问struct lxc\u container块中描述的函数 以下是我代码的一部分: #[link(name = "lxc")] extern { // LXC part fn lxc_get_version() -> *const c_char; fn lxc
lxc\u get\u version
或lxc\u container\u new
,但我无法访问struct lxc\u 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结构中的函数称为函数指针。我曾尝试在谷歌上搜索“Rust C function pointer”之类的东西,但运气不好。当你看到这样的东西时(在C中): 这意味着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;
}
这里,结构实例s1
包含指向某些函数\u 1
的指针,s2
包含指向某些函数\u 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\u f
括在括号中,以消除方法调用和字段访问之间的歧义
你可以在Rust中找到更多关于FFI的信息。函数指针的解释非常简单。谢谢您的回答,我现在可以访问函数指针了。我已经为C表示编写了一个结构,并围绕它编写了一个Rust表示的包装器。不幸的是,我无法调用
is_defined
,因为我无法将LxcContainer结构传递给函数*LxcContainer。出现解引用错误。你能在你的答案中添加一些函数指针调用的例子吗?谢谢。@bbrodriges,很抱歉回复太晚,但我已经用一个如何调用存储在struct字段中的函数的示例更新了我的答案。
impl LxcContainer {
fn is_defined_f(&mut self) -> bool {
unsafe {
(self.is_defined_f)(self as *mut LxcContainer)
}
}
}