Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the purpose of writing bindings for C libraries for Rust?

Tags:

rust

I was under the impression that bindings are intermediate layers you write so that you may use a library written in one language in an application written in another. It seems that Rust may call C with zero overhead

For a concrete example, Vulkan is a C API, yet people are working on bindings for Vulkan (1, 2, 3).

If C can be called directly from Rust, why would you want to create bindings? Have I misunderstood something?

like image 880
Andreas Flöjt Avatar asked Mar 22 '16 12:03

Andreas Flöjt


People also ask

What are Rust bindings?

Rust refers to all declarations as Bindings as they bind a name you create to some type of data. All bindings begin with let . let x = 1; This will bind x to the value of 1 . Rust has strong type inference so we did not have to specify what type x would be, the compiler automatically figured it out.

Can I use C libraries in Rust?

Rust natively supports linking against C libraries and calling their functions directly. Of course, any function imported thus requires the unsafe keyword to actually call (because Rust can't guarantee its invariants or correctness) but that's an inconvenience we can punt until later.

How do you write bindings in Rust?

To write bindings we need to call the C functions from rust code. To accomplish this rust provides us with foreign function interface(FFI) to talk with C. Before we call any C function from rust, we first need to declare that function in rust. We use the extern block provided by FFI for this.

How do C libraries work?

C libraries store files in object code; during the linking phase of the compilation process ( Compilation Process) files in object code are accessed and used. It is faster to link a function from a C library than to link object files from a separate memory sticks or discs.


1 Answers

While Rust can call C functions without overhead, the Rust compiler still needs to know about the existence of those functions. To tell the compiler you have to declare those functions in an extern "C" { .. } block. You can read more about the topic in the FFI chapter of the Rust book. For C functions that are used by many people (e.g. Vulkan), it makes sense to put all those declarations into a Rust library that others can just use, instead of writing the bindings themselves.

With the bindings mentioned above we simply expose the original C interface to the Rust programmer. But most Rust programmers rather want to use an API that is idiomatic in Rust (we call it "rusty"). That is: using high level concepts of Rust, like traits and closures, and being "safe".

The Vulkan libraries you linked:

  • The second link is just is a raw binding generated with a tool (rust-bindgen).

  • The purpose of tomaka's library is to create a rusty API, so it isn't just a collection of function declarations. tomaka chooses to introduce very little overhead in order to create a library that most Rust programmers are more comfortable to use than the C interface. (by the way: tomaka did this for OpenGL, too).

  • I don't really know about the first library you linked, but I think it's something in between the two approaches above.

like image 57
Lukas Kalbertodt Avatar answered Nov 22 '22 11:11

Lukas Kalbertodt