1 个不稳定版本
使用旧的Rust 2015
0.1.0 | 2016年11月22日 |
---|
#33 在 #memory-safe
9KB
117 行
#func-swap 交换函数!
这个crate是一个宏,允许你定义一个可以在运行时与其他函数(同一符号)热插拔的函数。即使在并发系统中,交换也是内存安全的。开销只是一个指针加载,以及在函数开始时的一个 if != 0
跳转(在AMD64/ARMv8上)。在较老的ARM上,调用时有一个加载内存屏障,这是最便宜的屏障。
替换函数会触发一个完整的 Ordering::SeqCst
内存屏障,以确保所有后续调用都将看到新函数。
要使用此crate,请包含
[dependencies]
func_swap = "0.0.1"
lazy_static = "0.2.*"
示例用法
#[macro_use]
extern crate func_swap;
#[macro_use]
extern crate lazy_static;
//define the add function so it is replaceable
modfunc!(replace,FP, add(x: u64, y: u64) => u64{
x + y
});
assert!( add(5u64,2u64) == 7u64);
//define a completely different function
fn not_addition(x: u64, y: u64) -> u64 {
(x*x)+y
}
//swap the values
replace(not_addition);
assert!( add(5u64,2u64) == 27u64);
为了阐明这个宏
modfunc!(
SWAP_FUNCTION: ident, //define a function to swap functions
FUNCTION_POINTER: ident, //define a constant, this name will really shouldn't be used
SWAPPABLE: ident //define the main function
( var:type, var2:type) //args
type OR (type,type,...) //return values
{
//body of your function
});
##问答
###我可以使用泛型吗?
不可以。函数签名需要在编译时是具体的和已知的。你可能可以用TraitObjects。但我还没有测试过。YYMV
###我可以捕获值吗?
不。这不是一个lambda表达式,这是一个定义静态函数。
###我可以与通过动态链接加载的函数交换吗?
是的。但请谨慎使用。当你卸载库时,一些标志将使现有的函数指针无效。这可能导致函数调用未分配的虚拟内存...从而导致SEGFAULT。
如果你卸载一个函数,确保将其设置为NULL。 unsafe{mem::transmute(0usize)
。这将恢复默认行为。
###默认使用哪种ABI?
使用的是 extern "Rust"
ABI。需要注意的是这是非稳定的。所以如果你是动态链接,请使用与Rust编译器相同修订版本的SO/DLL生成的。
###我可以使用非Rust ABI吗?
是的。如果你以 @ABI:
开始宏,第一个参数是ABI的表达式。这看起来像
modfunc!(ABI: "C", swap_function, functionptrname, function(args: yada)
这个特性还没有经过大量测试,YYMV。还应该注意的是,默认函数将保持为本地函数。
依赖项
~14KB