公开包含从Rust到C的函数指针的零终止数组的C符号
我有下面的C代码,它被编译为公开包含从Rust到C的函数指针的零终止数组的C符号,rust,ffi,Rust,Ffi,我有下面的C代码,它被编译为。因此: void (*vlog_startup_routines[])() = { hello_register, 0 }; 在Rust中,我可以使用#[no\u mangle]声明函数。如何公开名为vlog\u startup\u routines的符号,该符号是一个包含函数指针的数组,也是以零结尾的?您需要定义一个类型为数组的静态项。不幸的是,在定义静态项时,我们需要指定该数组的大小(从1.13.0开始) Rust中的函数指针不被认为是不安全的
。因此
:
void (*vlog_startup_routines[])() = {
hello_register,
0
};
在Rust中,我可以使用
#[no\u mangle]
声明函数。如何公开名为vlog\u startup\u routines
的符号,该符号是一个包含函数指针的数组,也是以零结尾的?您需要定义一个类型为数组的静态
项。不幸的是,在定义静态
项时,我们需要指定该数组的大小(从1.13.0开始)
Rust中的函数指针不被认为是不安全的调用(除非您有一个不安全的fn
)。然而,调用空指针并不安全,因此Rust不允许创建空函数指针。但是有一个技巧:当T
是指针时(无论哪种类型的指针,包括胖指针和函数指针)。因此,我们可以定义一个选项
值数组来获得所需的结果
1对于其他类型,选项
将大于T
以存储判别式
#[no_mangle]
#[allow(non_upper_case_globals)]
pub static vlog_startup_routines: [Option<fn()>; 2] = [
Some(hello_register),
None
];
注意:宏的
one\u存在是因为我们需要引用重复模式中的一个参数符号(您可以有多个不同的重复,因此编译器需要知道您引用的是哪一个),但我们不关心它的值。有趣。数组只不过是一个指针,以0结尾是一个运行时属性。但是,我不知道如何跨FFI边界传递函数指针;你检查过现有的防锈文件了吗?@MatthieuM。这里基本上不存在数组指针<代码>(void*)hello_register==(void*)vlog_startup_例程
,对吗?我建议在提问时使用你的措辞。提供C代码使其看起来像是要调用该代码。最好提供使用extern
的C代码来突出显示您希望在Rust中实现该符号。此外,当您有一个库时,没有任何东西可以驱动程序,因此不会调用任何东西。C可执行文件可以更好地表达这个问题。@Shepmaster:请注意*hello\u register==vlog\u startup\u例程
,因为数组包含指向函数的指针,而不是函数本身,我想如果希望拥有多个函数,这很重要。所以在Rust中,hello\u register
将类似于*const fn()
我想,允许算术运算。@MatthieuM。也许你能帮我找出原因吗?None
;当然我不知道如何使用适当的类型创建NULL
。叹气。谢谢,我考虑过这个选项,但我认为可能有更好的选择,因为只有最后一个元素应该是0。我想还没有。
macro_rules! one_for {
($_x:tt) => (1)
}
macro_rules! vlog_startup_routines {
($($func:expr,)*) => {
#[no_mangle]
#[allow(non_upper_case_globals)]
pub static vlog_startup_routines: [Option<fn()>; $(one_for!($func) +)* 1] = [
$(Some($func),)*
None
];
}
}
vlog_startup_routines! {
hello_register,
}