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

[feature request] request a `--wrap-inline-fns` flag, for wrapping inline functions

Open lulitao1997 opened this issue 1 year ago • 2 comments

although currently we have generate-inline-functions, this flag requires user modify the build script and adding -fkeep-inline-functions flag, which is not supported by clang.

i'm wondering if we could generate c file by wrapping these inline functions, similar to --wrap-static-fns

i'm happy to submit a pull request for this.

lulitao1997 avatar Dec 22 '24 05:12 lulitao1997

I did a bit of research on what these inline specifiers all mean. Here are some good resources:

  • https://en.cppreference.com/w/c/language/inline.html
  • https://en.cppreference.com/w/c/language/storage_class_specifiers.html
  • https://stackoverflow.com/questions/34937816/inline-static-extern-in-c99

According to the C99 standard, If you define a function in a header file (you write its implemntation there), then static, static inline, inline (without an extern declaration) all come without an emitted public symbol, and thus need to wrapped in order to be linkable.

If an inline definition ends up being not inlined (e.g. because optimizing for program size or because somebody took their addres), then it behaves similarly to static, so it doesn't provide an external symbol. If one wants to guarantee a linkable external symbol for their inline function, they can write an exten inline declaration in a single translation unit (without definition), which forces the compiler to emit an external symbol there.

As far as wrapping is concerned, you can always wrap a header-defined function with a different wrapper name. The current limitation of Bindgen seems unnecessary, and the recommendation of compiling the original C library without inlining enabled (-fno-inline-functions) is suboptimal, as in certain cases it may cause even the internals of a library to slow down, not just the bridg.

I think the best default approach for bindgen would be to wrap all inline, inline static, and static functions defined in header files into their uniquely named linkable C symbol (e.g. __extern suffix). There is nothing that's wrapped twice, and I also don't expect linker errors. Then if you really want to optimize for code size, and you happen to know that the library already exposes symbols for all or certain symbols, you could customize bindgen to not emit a new wrapper, as we could just use the one generated by the library.

The current default behavior is to not wrap any of the inline nor static functions. We may be able to add a new flag --wrap-header-definitions that replaces all the old flags, and wrap all inline, static inline, static functions. Alternatively, we could add --wrap-inline-fns, and then the user would need to add two flags usually (which I like slightly less). Note that the behavior of inline/extern changed significantly between GNU-C 89 to the C 99 standard, so I would advise this flag to only be available if you use C99+.

@pvdrz @lulitao1997 could you review these statements and see if this would be a suitable path?

tothambrus11 avatar Jun 21 '25 08:06 tothambrus11

the above and --wrap-header-definitions looks good to me, i would also add that we can similarly wrap C++ class member functions the same way, currently it also requires us to compile using -fno-inline-functions

lulitao1997 avatar Jun 24 '25 15:06 lulitao1997