5 ms·
"static inline", the best way of getting people doing bindings in other languages to dislike your library (macros are just as bad, FWIW). I really wish someone
by yxhuvud 8mo ago
"static inline", the best way of getting people doing bindings in other languages to dislike your library (macros are just as bad, FWIW).
I really wish someone on the C language/compiler/linker level took a real look at the problem and actually tried to solve it in a way that isn't a pain to deal with for people that integrate with the code.
- LtWorf 8mo agoIf it's not in the .h file it's supposed to be a private function.
- zabzonk 8mo agoyou can access it using extern from anywhere: // a.c int f( int x ) { return x + 1; } // b.c extern int f(int x ); int main() { int y = f(41); } but if f() had been defined as static, you couldn't do this.
- bigfishrunning 8mo ago"private function" doesn't mean "you can't know about this", it means "you shouldn't rely on this as a stable interface to my code". Just because you can use the information you have to call a given function, doesn't mean you aren't violating an interface.
- zabzonk 8mo agomy point was that f() had been defined static then you can't access it from outside the translation unit it is defined in - in other words, it is "private". i'm afraid i'm unclear what your point is.
- Nevermark 8mo agoBoth points are related and matter. For most purposes, not being able to access something, and being able to access something not officially in an interface, where doing so introduces an unpredictable breaking dependency, the practical result is the same: You can't (actually/sensibly) do it.
- zabzonk 8mo agoThen why not define "something" as static, which makes the compiler and linker guarantee that you can't do it?
- bigfishrunning 8mo agoWhat if I want to internally access it from multiple compilation units, but not necessarily encourage downstream users from using it? This is really common.
- yxhuvud 8mo ago`static inline` is definitely not private. See https://github.com/axboe/liburing/blob/master/src/include/liburing.h#L32 https://github.com/axboe/liburing/blob/master/src/include/li... , for a practical example.
- 1718627440 8mo agoIt's going to become private, but its part of your side of the interface, not of the other side. The ABI boundary is between that `static inline` function and the library, not between that function and your code.
- jlarocco 8mo agoI don't see what you're getting at with respect to writing bindings. The whole point of using "static" in that way is to prevent people from using it outside of the file. If you need to call a static function (inline or otherwise) from outside of the compilation unit to use the API, then it's a bug in the API, not a problem with static. I agree with you about pre-processor macros, though.
- zabzonk 8mo agoi think you replied to the wrong comment
- yxhuvud 8mo agoModern libraries consistently use `static inline`, to avoid the overhead of dynamic dispatch. Just take a look at liburing, and the client libraries for pipewire and wayland. All of them have `static inline` all over the place, for methods that are definitely intended to be called.
- Mikhail_Edoshin 8mo agoHere is a use case. I have a function that takes variable parameters, so there is no formal type control: int Foo(int a, ...); But in fact the types are restricted depending on a call type, set by 'a'. So I could add a wrapper for a specific variant: static inline FooVar1(char b, long c) { return Foo(FOO_VAR_1, b, c); } All the wrapper does is adds a bit of type control during compilation, otherwise it must be just a function call to 'Foo'. It is like a supermacro. It does make sense to put that into 'static inline' in a header.
- 1718627440 8mo agoThen what the FFI needs to target is `int Foo(int a, ...);`. FooVar1 is just a convenience method for the C language binding.
- yxhuvud 8mo agoThat is not an option - it may be layers on layers of them and force you to recreate half the library and force you to have to redo subsequent version updates in your code. Then a shim is the preferred solution. But anything that requires a C compiler for FFI is something that won't make anyone happy. Hence my claim that it really is something that needs fixing on the language or linker level.
- yxhuvud 8mo agoWhat makes you think functions defined as `static inline` is not in the .h? These are very much not private functions. Example: https://github.com/axboe/liburing/blob/master/src/include/liburing.h#L32 https://github.com/axboe/liburing/blob/master/src/include/li...
- LtWorf 8mo agoThey are basically using it instead of macros inside the header file. Do you have a relevant example?
- yxhuvud 8mo agoEssentially all the most important functions to interact with rings during runtime is static inline. The prep_* methods for sqes are so simple they are not problematic to reimplement, but all the other interactions necessary - submit, advance, peek, wait etc are all static inline, nested several layers. Those are not trivial and details have changed over time. Thankfully that particular library do nowadays also provide a _ffi version of the .so as it is such an horror otherwise. But there are other libraries out there that don't do that, where it is almost as big of a hurdle to bind with.
- wahern 8mo ago> I really wish someone on the C language/compiler/linker level took a real look at the problem and actually tried to solve it in a way that isn't a pain to deal with for people that integrate with the code. It exists as "inline" and "extern inline".[1] Few people make use of them, though, partly because the semantics standardized by C99 were the complete opposite of the GCC extensions at the time, so for years people were warned to avoid them; and partly because linkage matters are a kind of black magic people avoid whenever possible--"static inline" neatly avoids needing to think about it. [1] See C23 6.7.5 at https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf#page=137 https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf#p...
- yxhuvud 8mo ago> "static inline" neatly avoids needing to think about it. Sure, except when you do FFI bindings. Then those functions just don't exist and you get a linking error.
- sparkie 8mo agoCompile using `-fkeep-inline-functions`.
- yxhuvud 8mo agoDoesn't help. The point is to avoid having to invoke a C compiler when working in X language. But it would certainly be nice if the distros enabled that.