c_api_prefix/
lib.rs

1extern crate proc_macro;
2extern crate proc_macro2;
3extern crate syn;
4extern crate quote;
5
6use proc_macro::TokenStream;
7use proc_macro2::{Ident, Span};
8use quote::{quote, ToTokens};
9use syn::{parse_macro_input, ItemFn, Abi, Token, LitStr};
10
11#[proc_macro_attribute]
12pub fn c_api_prefix(attr: TokenStream, func: TokenStream) -> TokenStream {
13    let mut input = parse_macro_input!(func as ItemFn);
14    
15    let prefix = attr.to_string();
16    let name = input.sig.ident.to_string();
17
18    input.sig.ident = get_name(prefix, name);
19
20    input.sig.abi = abi_setting();
21    let tokens = input.to_token_stream();
22    TokenStream::from(
23        quote!{
24            #[no_mangle]
25            #tokens
26        }
27    )
28}
29
30fn abi_setting() -> Option<Abi> {
31    Some(Abi {
32        extern_token: Token![extern](Span::call_site()),
33        name: Some(LitStr::new("C", Span::call_site()))
34    })
35}
36
37fn get_name(prefix: String, name: String) -> Ident {
38    match prefix.as_str() {
39        "" => Ident::new(name.as_str(), Span::call_site()),
40        prefix => Ident::new(
41            format!("{}_{}", prefix, name).as_str(),
42            Span::call_site()
43        )
44    }
45}