| Crates.io | crate_interface |
| lib.rs | crate_interface |
| version | 0.1.4 |
| created_at | 2023-05-03 06:37:09.829304+00 |
| updated_at | 2025-01-18 14:08:07.719105+00 |
| description | Provides a way to define an interface (trait) in a crate, but can implement or use it in any crate. |
| homepage | https://github.com/arceos-org/arceos |
| repository | https://github.com/arceos-org/crate_interface |
| max_upload_size | |
| id | 855146 |
| size | 15,218 |
Provides a way to define an interface (trait) in a crate, but can implement or use it in any crate. It 's usually used to solve the problem of circular dependencies between crates.
// Define the interface
#[crate_interface::def_interface]
pub trait HelloIf {
fn hello(&self, name: &str, id: usize) -> String;
}
// Implement the interface in any crate
struct HelloIfImpl;
#[crate_interface::impl_interface]
impl HelloIf for HelloIfImpl {
fn hello(&self, name: &str, id: usize) -> String {
format!("Hello, {} {}!", name, id)
}
}
// Call `HelloIfImpl::hello` in any crate
use crate_interface::call_interface;
assert_eq!(
call_interface!(HelloIf::hello("world", 123)),
"Hello, world 123!"
);
assert_eq!(
call_interface!(HelloIf::hello, "rust", 456), // another calling style
"Hello, rust 456!"
);
The procedural macros in the above example will generate the following code:
// #[def_interface]
pub trait HelloIf {
fn hello(&self, name: &str, id: usize) -> String;
}
#[allow(non_snake_case)]
pub mod __HelloIf_mod {
use super::*;
extern "Rust" {
pub fn __HelloIf_hello(name: &str, id: usize) -> String;
}
}
struct HelloIfImpl;
// #[impl_interface]
impl HelloIf for HelloIfImpl {
#[inline]
fn hello(&self, name: &str, id: usize) -> String {
{
#[inline]
#[export_name = "__HelloIf_hello"]
extern "Rust" fn __HelloIf_hello(name: &str, id: usize) -> String {
let _impl: HelloIfImpl = HelloIfImpl;
_impl.hello(name, id)
}
}
{
format!("Hello, {} {}!", name, id)
}
}
}
// call_interface!
assert_eq!(
unsafe { __HelloIf_mod::__HelloIf_hello("world", 123) },
"Hello, world 123!"
);