Live data from Hacker News

The Dark Arts of Advanced and Unsafe Rust Programming

doc.rust-lang.org

1–10 of 26 posts

Re: The Dark Arts of Advanced and Unsafe Rust Programming

#2
I recently had to write a lot of unsafe code in C# to interoperate with a driver.

As advanced as modern languages are, the excellent memory models only work within the language. Interoperability requires that you can work with memory directly when needed. (And only when needed.) I don't have a lot of Rust experience, but C# has plenty of tricks to avoid unsafe code but get close enough to working with real memory.

One thing that would help is if there was some kind of a tool that could take C header files, figure out how the structs and functions compile, and generate the Rust / C# structs and fuction signatures. This is such a time consuming task to do manually in C#, and novices screw it up all the time.

(I wish I had the time to do more work in Rust. It's a great concept!)

Re: The Dark Arts of Advanced and Unsafe Rust Programming

#3
post #2

I recently had to write a lot of unsafe code in C# to interoperate with a driver. As advanced as modern languages are, the excellent memory models only work within the language. Interoperability requires that you can work with memory directly when needed. (And only when needed.) I don't have a lot of Rust experience, but C# has plenty of tricks to avoid unsafe code but get close enough to working with real memory. On…

There are a couple of projects that do this for Rust, depending on what your inputs and outputs are:

* https://github.com/rust-lang-nursery/rust-bindgen - Inputs are C/C++ headers, outputs are Rust type definitions and extern functions to interoperate with the type and functions in the headers

* https://github.com/immunant/c2rust - Inputs are C headers and source, outputs Rust code that is semantically equivalent to the C (modulo bugs, etc.)

* https://github.com/eqrion/cbindgen/ - Inputs are Rust source, outputs C/C++ headers that can be used to interoperate with the types and functions exposed by Rust

Re: The Dark Arts of Advanced and Unsafe Rust Programming

#4
post #2

I recently had to write a lot of unsafe code in C# to interoperate with a driver. As advanced as modern languages are, the excellent memory models only work within the language. Interoperability requires that you can work with memory directly when needed. (And only when needed.) I don't have a lot of Rust experience, but C# has plenty of tricks to avoid unsafe code but get close enough to working with real memory. On…

Taking header files and automatically generating Rust FFI code to match is exactly what rust-bindgen does

https://github.com/rust-lang-nursery/rust-bindgen

Re: The Dark Arts of Advanced and Unsafe Rust Programming

#5
post #2

I recently had to write a lot of unsafe code in C# to interoperate with a driver. As advanced as modern languages are, the excellent memory models only work within the language. Interoperability requires that you can work with memory directly when needed. (And only when needed.) I don't have a lot of Rust experience, but C# has plenty of tricks to avoid unsafe code but get close enough to working with real memory. On…

This isn’t really enough. What you really want is something that hoists C memory management into the the language you’re using; for example, the constructor for a high-level type would manage allocating memory and calling the constructor function, and the deinitializer would map to the custom free/close/release method. This isn’t really anything that I think can be automated; you’re going to have to write this wrapper yourself or find someone who’s already done it.

Re: The Dark Arts of Advanced and Unsafe Rust Programming

#6
post #2

I recently had to write a lot of unsafe code in C# to interoperate with a driver. As advanced as modern languages are, the excellent memory models only work within the language. Interoperability requires that you can work with memory directly when needed. (And only when needed.) I don't have a lot of Rust experience, but C# has plenty of tricks to avoid unsafe code but get close enough to working with real memory. On…

"take C header files, figure out how the structs and functions compile, and generate the Rust / C# structs and fuction signatures. "

I have been playing with idea but often you also need to know what the function does with the pointer you pass in. Is it "in", "out" or whatever? With a lot of functions it would be doable but there are quite a few Win32 functions where it's really, really hard to do direct interop from C#. For these cases I find C+/CLI wrappers easier to deal with.

Re: The Dark Arts of Advanced and Unsafe Rust Programming

#7
post #2

I recently had to write a lot of unsafe code in C# to interoperate with a driver. As advanced as modern languages are, the excellent memory models only work within the language. Interoperability requires that you can work with memory directly when needed. (And only when needed.) I don't have a lot of Rust experience, but C# has plenty of tricks to avoid unsafe code but get close enough to working with real memory. On…

This isn’t really enough. What you really want is something that hoists C memory management into the the language you’re using; for example, the constructor for a high-level type would manage allocating memory and calling the constructor function, and the deinitializer would map to the custom free/close/release method. This isn’t really anything that I think can be automated; you’re going to have to write this wrappe…

You might be able to kernelize it in a way where other language features are built on top of it. That's what House team did for a Haskell-based OS with unsafe stuff was stuffed into the H Layer.

http://programatica.cs.pdx.edu/House/

Likewise, metaprogramming routines that generate C code or interfaces for you from language statements closer to host.

Re: The Dark Arts of Advanced and Unsafe Rust Programming

#8
post #2

I recently had to write a lot of unsafe code in C# to interoperate with a driver. As advanced as modern languages are, the excellent memory models only work within the language. Interoperability requires that you can work with memory directly when needed. (And only when needed.) I don't have a lot of Rust experience, but C# has plenty of tricks to avoid unsafe code but get close enough to working with real memory. On…

bindgen does this, and in particular bindgen is great because it uses libclang to parse the C header files, so it's interpreting them the same way that clang would.

I'm using bindgen in a project to bind the Linux kernel headers, which makes me a little bit uncomfortable because the Linux kernel is only guaranteed to compile with GCC (and may use GCC-specific extensions in describing structure layout) and in particular there's no guarantee that the in-kernel ABI is stable across different compilers. But it seems to work well in practice, as long as I tell bindgen not to attempt to parse literally everything (which it fails at).

That said - if you're interoperating with memory-mapped IO or with memory mapped from a foreign process, the other thing to be very careful about is that almost all languages (including C!) by default only make sure that memory writes are coherent from the viewpoint of other code in that language, and not necessarily that they're coherent from the viewpoint of something looking directly at memory. It's generally permissible to write a 64-bit number by writing each 32-bit half separately. It's generally permissible to write something and overwrite it immediately, or combine multiple writes, or so forth. In addition to structure layout, you probably want volatile read/write operations, same as you'd want volatile pointers in C: https://doc.rust-lang.org/std/ptr/fn.read_volatile.html or the atomic types with the "SeqCst" barrier https://doc.rust-lang.org/std/sync/atomic/index.html .

Re: The Dark Arts of Advanced and Unsafe Rust Programming

#9
post #8
post #2

I recently had to write a lot of unsafe code in C# to interoperate with a driver. As advanced as modern languages are, the excellent memory models only work within the language. Interoperability requires that you can work with memory directly when needed. (And only when needed.) I don't have a lot of Rust experience, but C# has plenty of tricks to avoid unsafe code but get close enough to working with real memory. On…

bindgen does this, and in particular bindgen is great because it uses libclang to parse the C header files, so it's interpreting them the same way that clang would. I'm using bindgen in a project to bind the Linux kernel headers, which makes me a little bit uncomfortable because the Linux kernel is only guaranteed to compile with GCC (and may use GCC-specific extensions in describing structure layout) and in particul…

You probably won't have too many problems, Google and friends have had a long running project to get the kernel to compile with clang.

Unfortunately, they're not done yet. A guy I bumped into at a Linux kernel conference once said that their main issue is that some people within the kernel project want to keep GCC as the only way to compile the kernel.

Re: The Dark Arts of Advanced and Unsafe Rust Programming

#10
Ada does, and has better and more clear conventions for "unsafe" programming (pointer arithmetic, conversions, etc) but does it naturally without special keywords and esoteric conventions through its package system. Too bad no one will ever give it a chance due to is syntax :(

Rust is nothing but a slapdash C style copy of its semantics.

Post reply on HN