rust-bindgen icon indicating copy to clipboard operation
rust-bindgen copied to clipboard

rust-bindgen generate from C macro

Open cppcoffee opened this issue 1 year ago • 6 comments

I want to generate corresponding Rust macro definitions from C language macro definitions, input C header as follow:

// test.h
enum { FRAME_TYPE, FRAME_TYPEP, FRAME_LUA };

#define frame_type(f) ((f) & FRAME_TYPE)

Run bindgen command:

$ bindgen ./test.h --default-enum-style moduleconsts --no-layout-tests --no-derive-default --use-core --ctypes-prefix ::aya_ebpf::cty --generate functions,types,vars,methods,constructors,destructors --no-doc-comments --no-prepend-enum-name --rust-target 1.82.0 --clang-macro-fallback -- -Wno-unknown-attributes

Output rust as follow:

/* automatically generated by rust-bindgen 0.71.1 */

pub mod _bindgen_ty_1 {
    pub type Type = ::aya_ebpf::cty::c_uint;
    pub const FRAME_TYPE: Type = 0;
    pub const FRAME_TYPEP: Type = 1;
    pub const FRAME_LUA: Type = 2;
}

The expectation is to have the frame_type macro definition.

Here is the related issue:

https://github.com/aya-rs/aya/issues/1128

https://github.com/aya-rs/aya/pull/1129

cppcoffee avatar Jan 03 '25 13:01 cppcoffee

The expectation is to have the frame_type macro definition.

What do you mean by "macro definition"? A Rust macro? A const fn? i.e. please post the expected Rust code you would like to see generated.

The Clang macro fallback linked above is (so far, and as far as I always understood it) intended to resolve macros that evaluate to a constant, not to generate code for arbitrary macros.

This would be closer to a --wrap-static-fns but for macros.

Cc @jbaublitz

ojeda avatar Jan 03 '25 14:01 ojeda

Generating corresponding Rust code from C language macro definitions would be sufficient, whether as Rust functions or Rust macros.

This approach would be better for C projects that involve numerous macro definitions.

Like this:

#define frame_type(f)		(frame_ftsz(f) & FRAME_TYPE)
#define frame_typep(f)		(frame_ftsz(f) & FRAME_TYPEP)
#define frame_islua(f)		(frame_type(f) == FRAME_LUA)

#define frame_ftsz(f)		((ptrdiff_t)(f)->ftsz)
#define frame_pc(f)		((const BCIns *)frame_ftsz(f))

#define frame_prevl(f)		((f) - (1+LJ_FR2+bc_a(frame_pc(f)[-1])))
#define bc_a(i)		((BCReg)(((i)>>8)&0xff))

cppcoffee avatar Jan 03 '25 14:01 cppcoffee

Generating corresponding Rust code from C language macro definitions would be sufficient, whether as Rust functions or Rust macros.

That would be very useful indeed (even if only for a small subset of cases) -- please see https://github.com/rust-lang/rust-bindgen/pull/2369.

ojeda avatar Jan 03 '25 15:01 ojeda

Hi @ojeda, is this something that would be considered another desired feature for Rust for Linux?

jbaublitz avatar Jan 06 '25 15:01 jbaublitz

I think in general a tool that would automate some of these would be quite useful for some projects, e.g. in Linux we already had to rewrite ioctl macros (like _IOC(dir,type,nr,size), e.g. see rust/kernel/ioctl.rs).

However, it is non-trivial (it gets closer to a transpiler), and especially with macros, since there may be different potential useful solutions for each macro depending on the use case (how they are called).

For instance, for a f(x) macro that expands to x * 2, cmacro (used in the PR) converts it (from a quick look to its tests, Cc @reitermarkus) to a Rust macro doing exactly the same syntax-wise. However, in some use cases the user may be interested in reproducing particular semantics of C types (e.g. wrapping for unsigned integers, i.e. not expecting a panic), rather than actually using Rust's * operator as-is. One could pass Rust types that mimic behavior for those operators, I guess, but in many cases a const fn with particular types, or possibly generic, may make more sense.

So it is possible extra input/information/context from the user may be needed to decide. Perhaps this is the sort of problem where such a tool is best used to get potential solutions and then the developer picks and adapts the right one.

ojeda avatar Jan 06 '25 20:01 ojeda

So you're suggesting actually converting from C macros to Rust macros?

jbaublitz avatar Jan 07 '25 20:01 jbaublitz