Is c_variadic in 1.45.0 stable? Or do I need a nightly build

I have rustc 1.45.0 installed.
Release notes says c_variadic is installed in 1.42.0

Yet I am seeing the following error

error: only foreign or `unsafe extern "C" functions may be C-variadic
  --> src/lib.rs:32:60
   |
32 |     pub unsafe extern "C" fn printf(format: *const c_char, mut args: ...) -> c_int  {
   |                                                            ^^^^^^^^^^^^^^

error[E0658]: C-variadic functions are unstable
  --> src/lib.rs:32:5
   |
32 | /     pub unsafe extern "C" fn printf(format: *const c_char, mut args: ...) -> c_int  {
33 | |         if redhook::initialized() {
34 | |             ::std::panic::catch_unwind(|| my_printf (format)).ok()
35 | |         } else {
36 | |             None
37 | |         }.unwrap_or_else(|| printf.get() (format))
38 | |     }
   | |_____^
   |
   = note: see issue #44930 <https://github.com/rust-lang/rust/issues/44930> for more information

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0658`.

If I add

#![feature(c_variadic)]

I see the following asking me to use nightly

error[E0554]: `#![feature]` may not be used on the stable release channel
 --> src/lib.rs:1:1
  |
1 | #![feature(c_variadic)]

According to the linked issue, Tracking issue for RFC 2137: Support defining C-compatible variadic functions in Rust · Issue #44930 · rust-lang/rust · GitHub, this has been implemented but not stabilized.

Note that in the release notes for 1.42.0, stabilizing ... is makred as a syntax-only change:

There are some syntax-only changes:

  • default is syntactically allowed before items in trait definitions.
  • Items in impl s (i.e. const s, type s, and fn s) may syntactically leave out their bodies in favor of ; .
  • Bounds on associated types in impl s are now syntactically allowed (e.g. type Foo: Ord; ).
  • ... (the C-variadic type) may occur syntactically directly as the type of any function parameter.

This means that this parses now, but not much else. I think it means attribute-like macros can consume function definitions with ..., as long as the output is transformed so that it's removed. It's a stabilization in the syntax, but not in the functionality.

I installed the nightly rust
Still seeing an error with c_variadic. The code is a simple variadic printf to intercept libc printf function.

 error: only foreign or `unsafe extern "C" functions may be C-variadic
  --> src/lib.rs:33:61
   |
33 |     pub unsafe extern "C" fn printf(_format: *const c_char, mut _args: ...) -> c_int  {
   |                                                             ^^^^^^^^^^^^^^^

error: aborting due to previous error

error: could not compile `redhook_ex_varopenspy`.

The code is bellow.

#![feature(c_variadic)]

extern crate libc;

// #[macro_use]
extern crate redhook;

use libc::{c_char,c_int};


#[allow(non_camel_case_types)]
pub struct printf {__private_field: ()}
#[allow(non_upper_case_globals)]
static printf: printf = printf {__private_field: ()};


impl printf {
    #[no_mangle]
    pub unsafe extern "C" fn printf(_format: *const c_char, mut args: ...) -> c_int  {
        10
    }
}

While non variadic in this same case compiles

#![feature(c_variadic)]

extern crate libc;

// #[macro_use]
extern crate redhook;

use libc::{c_char,c_int};


#[allow(non_camel_case_types)]
pub struct printf {__private_field: ()}
#[allow(non_upper_case_globals)]
static printf: printf = printf {__private_field: ()};


impl printf {
    #[no_mangle]
    pub unsafe extern "C" fn printf(_format: *const c_char) -> c_int  {
        10
    }
}

compiles fine.

Like @daboross said, it's only implemented on the syntactic level. Trying to use it for anything more than that (eg implementing a function) therefore has no chance of working, even in nightly rust.

Only the syntax is is stable, but according to the issue, it's all implemented.

The C-vardiac feature was implemented in https://github.com/rust-lang/rust/pull/57760, and that implementation is still in nightly. Here's a test which uses it, for example.

@sarvi In your particular example, I believe the problem is probably that you've written it as a method, not a function? Like, it seems to only be supported for freestanding functions, not for methods declared in impl blocks.

If I change your function definition to a freestanding function, then it compiles:

#![feature(c_variadic)]

extern crate libc;

use libc::{c_char,c_int};

#[no_mangle]
pub unsafe extern "C" fn printf(_format: *const c_char, mut args: ...) -> c_int  {
    10
}

I don't know if the lack of support for methods is intended, or a bug. It might be worth raising this as an issue in the rust repo?

Thx daboross.
It does work as a function an not as a method.
Should I report it as issue in the issue?

Because non-c_varadic ones work both as standalone functions and as method.
The crate redhook for example uses that method behaviour to provide a very nice library to build ld_preload programs very conveniently.

And these use this approach and it looks very simple and clean.

Will probably report it

Since other extern functions work as methods, I'd go ahead and report it.

On stable there's a hacky workaround:

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.