Extern "C" as a block

I'm exporting a bunch of C functions in a static library. For each function, I have to write:

#[no_mangle]
pub extern "C" fn function_name() {
  . . .
}

Is there any way to do this in a block so that I don't have to write this for every function?

#[no_mangle]
pub extern "C" . . .

No, there isn't. You could create a macro or even automate it with a proc_macro, but in the end the compiler wants this on every single function individually.

1 Like

Bummer. It adds a lot of extra cruft that ultimately seems unnecessary.

We really should be able to do something like this:

#[no_mangle]
pub extern "C" {
  fn function_1() {
    . . .
  }

  fn function_2() {
    . . .
  }

  . . .
}

I agree that something like that would be nicer. You can get something similar using a macro, as kornel said. For example to get this:

export_functions! {
    fn function_1() {
        . . .
    }
    fn function_2() {
        . . .
    }
}

But to do this you need to define a hairy looking macro (someone better at macros might be able to improve this):

macro_rules! export_functions {
    ($( $(#[$meta:meta])* fn $name:ident ($($arg:ident: $arg_type:ty),*) $(-> $rtn_type:ty)? $body:block )*) => {
        $(
            $(#[$meta])*
            #[no_mangle]
            pub extern "C" fn $name($($arg: $arg_type),*) $(-> $rtn_type)? $body
        )*
    }
}
1 Like

That's what I was going to attempt next. Thanks for posting the solution.

Bummer. cbindgen doesn't see the functions if they in a macro.

Ah, that's a pain. I think it's possible to tell cbindgen to expand a macro but I'm not familiar enough with it to say how.