#run-time #style #macro #proc-macro #ifunc #indirect-once #indirection

indirect-once-derive

类似glibc的ifunc风格的一次性可解析运行时间接引用

3个不稳定版本

0.2.0 2021年1月1日
0.1.1 2021年1月1日
0.1.0 2021年1月1日

#275#style


indirect-once 中使用

MIT/Apache

5KB
92

indirect-once

类似glibc的 ifunc 的一次性可解析运行时间接引用。

Crates.io Docs.rs GitHub top language

用法

indirect-once 包提供了一些宏来帮助实现类似glibc的 ifunc 的运行时间接引用(但不需要特殊的编译器支持)。暴露的API旨在在精神上与 ifunc API相似,但具有Rust风格。

示例

indirect-once 支持两种宏风格。

过程宏

默认风格是属性过程宏。这种风格看起来更简洁,更接近原始的 ifunc(也被作为属性暴露)。这种风格的缺点是它会引入对一些过程宏工具包的依赖,这可能会增加编译时间(如 synproc_macro2quote 等)。如果您认为保持依赖图小或尽量降低编译时间非常重要,可以通过禁用 proc-macro 功能来选择退出。

use indirect_once::*;

// Two implementations of foo. One should be picked at runtime based on hardware features.
fn foo_with_avx(x: i32, y: u8, p: bool) -> u16 { unimplemented!() };
fn foo_with_sse(x: i32, y: u8, p: bool) -> u16 { unimplemented!() };

// A resolver function to decide which to pick. Gets called at most once, the first time foo is called.
fn resolve_foo() -> &'static fn(i32, u8, bool) -> u16 {
	if(cpu_has_avx!()) {
	  &(foo_with_avx as _)
	} else {
	  &(foo_with_sse as _)
	}
}

// Now define the real foo.

#[indirect(resolver = "resolve_foo")]
pub fn foo(x: i32, y: u8, p: bool) -> u16 {}

macro_rules!

另一种宏风格是简单的 macro_rules! 宏。生成的代码非常相似,但它不会引入任何过程宏包。

use indirect_once::*;

// Two implementations of foo. One should be picked at runtime based on hardware features.
fn foo_with_avx(x: i32, y: u8, p: bool) -> u16 { unimplemented!() };
fn foo_with_sse(x: i32, y: u8, p: bool) -> u16 { unimplemented!() };

// A resolver function to decide which to pick. Gets called at most once, the first time foo is called.
fn resolve_foo() -> &'static fn(i32, u8, bool) -> u16 {
	if(cpu_has_avx!()) {
	  &(foo_with_avx as _)
	} else {
	  &(foo_with_sse as _)
	}
}

// Now define the real foo.

pub indirect_fn! {
  resolver = resolve_foo; fn foo(x: i32, y: u8, p: bool) -> u16 {}
}

行为

在两种风格中,在宏或属性中指定的 resolver 参数中的函数只在新声明的函数第一次被调用时调用一次。

默认情况下,实现使用 std::sync::Once,但 parking-lot 功能将其替换为基于 parking_lot::Once 的后端。在任何情况下,一旦解析器运行了一次,这应该是一个简单的原子加载。

许可证

indirect-once 在 MIT 许可证和 Apache 2.0 许可证下双许可。您可以选择您更喜欢的任何一个。

依赖项

~1.2–6.5MB
~38K SLoC