5 ms·
Maybe they are asking the wrong questions? Does Rust need to change to make it easier to call C? I've done a bit of Rust, and (as a hobbyist,) it's still not
by gwbas1c 2y ago
Maybe they are asking the wrong questions?
Does Rust need to change to make it easier to call C?
I've done a bit of Rust, and (as a hobbyist,) it's still not clear (to me) how to interoperate with C. (I'm sure someone reading this has done it.) In contrast, in C++ and Objective C, all you need to do is include the right header and call the function. Swift lets you include Objective C files, and you can call C from them.
Maybe Rust as a language needs to bend a little in this case, instead of expecting the kernel developers to bend to the language?
- tupshin 2y agoThis is not a notable challenge in rust, nor relevant to the article. The article is about finding ways of using rust to actually implement kernel fs drivers/etc. Note that any rust code in the kernel is necessarily consuming C interfaces. Bindgen works quite well for the use case that you are thinking. https://github.com/rust-lang/rust-bindgen https://github.com/rust-lang/rust-bindgen
- moomin 2y agoYeah, the Rust proponents are being significantly more ambitious. Not just the ability to code a file system in Rust, but do it in a way that catches a lot of the correctness issues relating to the complex (and changing) semantics of FS development.
- codetrotter 2y agoI’ve written Rust code that called C++ It wasn’t completely straightforward, but on the whole I figured out everything I needed to within a few days in order to be able to do it. Calling C would surely be very similar.
- duped 2y agoIt's actually pretty easy. All you need is declare `extern "C" fn foo() -> T` to be able to call it from Rust, and to pass the link flags either by adding a #[link] attribute or by adding it in a build.rs. You can use the bindgen crate to generate bindings ahead of time, or in a build.rs and include!() the generated bindings. Normally what people do is create a `-sys` crate that contains only bindings, usually generated. Then their code can `use` the bindings from the sys crate as normal. > in contrast, in C++ and Objective C, all you need to do is include the right header and link against the library.
- lambda 2y agoCalling C from Rust can be quite simple. You just declare the external function and call it. For example, straight out of the Rust book https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html#usin... : extern "C" { fn abs(input: i32) -> i32; } fn main() { unsafe { println!("Absolute value of -3 according to C: {}", abs(-3)); } } Now, if you have a complex library and don't want to write all of the declarations by hand, you can use a tool like bindgen to automatically generate those extern declarations from a C header file: https://github.com/rust-lang/rust-bindgen https://github.com/rust-lang/rust-bindgen There's an argument to be made that something like bindgen could be included in Rust, not requiring a third party dependency and setting up build.rs to invoke it, but that's not really the issue at hand in this article. The issue is not the low-level bindings, but higher level wrappers that are more idiomatic in Rust. There's no way you're going to be able to have a general tool that can automatically do that from arbitrary C code.
- Smaug123 2y agoThe point is that Rust can model invariants that C can't. You can call both ways, but if C is incapable of expressing what Rust can, that has important implications for the design of APIs which must be common to both.
- gwbas1c 2y agoThat's not how I interpreted it: There is a clear need to be able to write filesystems in Rust, and the kernel developer(s) who write the filesystem API don't want to have to maintain the bindings to Rust.
- Smaug123 2y agoThey say this in almost every paragraph! For example, five of the first seven paragraphs: > The first is to express more of the requirements using Rust's type system in order to catch more mistakes at compile time. > Almeida showed an example of how the Rust type system can eliminate certain kinds of errors. > … it was exactly that kind of discussion/argument that could be avoided by encapsulating the rules into the Rust types and abstractions; the compiler will know the right thing to do. > … All of that is enforced through the type system. > the whole idea is to determine what the constraints are from Viro and other filesystem developers, then to create types and abstractions that can enforce them. More explicitly: > The object lifecycles are being encoded into the Rust API, but there is no equivalent of that in C; if someone changes the lifecycle of the object on one side, the other will have bugs. > As those changes occur, "we will find out whether or not this concept of encoding huge amounts of semantics into the type system is a good thing or a bad thing".
- gwbas1c 2y ago> In addition, when the C code changes, the Rust code needs to follow along, but who is going to do that work? Almeida agreed that it was something that needs to be discussed. FWIW: I shipped a Windows file system driver in 2020. The api hadn't changed in years. Does Linux's API for kernel-space filesystems really change so rapidly that keeping the rust bindings up-to-date would be a considerable amount of work, in the long run?
- kelnos 2y ago> Does Rust need to change to make it easier to call C? No, because it's already dirt-simple to do. You just declare the C function as 'extern "C"', and then call it. (You will often need to use 'unsafe' and convert or cast references to raw pointers, but that's simple syntax as well.) There are tools (bindgen being the most used) that can scan C header files and produce the declarations for you, so you don't have to manually copy/paste and type them yourself. > Maybe Rust as a language needs to bend a little in this case, instead of expecting the kernel developers to bend to the language? I think you maybe misunderstood the article? There's nothing wrong with the language here. The argument is around how Rust should be used. The Rust-for-Linux developers want to encode semantics into their API calls, using Rust's features and type system, to make these calls safer and less error-prone to use. The people on the C side are afraid that doing so will make it harder for them to evolve the behavior and semantics of their C APIs, because then the Rust APIs will need to be updated as well, and they don't want to sign up for that work. An alternative that might be more palatable is to not make use of Rust features and the type system in order to encode semantics into the Rust API. That way, it will be easier for C developers, as updating Rust API when C API changes will be mechanical and simple to do. But then we might wonder what the point is of all this Rust work if the Rust-for-Linux developers can't use Rust some features to make better, safer APIs. > I've done a bit of Rust, and (as a hobbyist,) it's still not clear (to me) how to interoperate with C. Kinda weird that you currently have the top-voted comment when you admit you don't understand the language well enough to have an informed opinion on the topic at hand.
- emporas 2y agoIf you like to see some examples of C bindings: https://github.com/tree-sitter/tree-sitter/blob/25c7189180849be27b1e552d27f0488e3bd5900d/tags/src/c_lib.rs https://github.com/tree-sitter/tree-sitter/blob/25c718918084...