#swap #define #memory-safe #run-time #function #macro #replace

func_swap

一个宏,用于定义一个函数,可以被其他函数替换

1 个不稳定版本

使用旧的Rust 2015

0.1.0 2016年11月22日

#33#memory-safe

Apache-2.0

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