[GH-ISSUE #688] Create C bindings #392

Closed
opened 2026-02-27 19:30:22 +03:00 by kerem · 0 comments
Owner

Originally created by @Johannesd3 on GitHub (Apr 11, 2021).
Original GitHub issue: https://github.com/librespot-org/librespot/issues/688

@d4rwel inspired me to write down some thoughts I had about creating C bindings for librespot. There's no need to change anything in librespot itself, it could happen in its own crate/repo. However, I assume that #665 is ready, but this could be accomplished with git dependencies.

So here's a rough plan:

Create a rust library crate and add the following to the Cargo.toml:

[dependencies]
librespot = "choose version"
tokio = "choose version"

[lib]
crate-type = ["cdylib"]

Pick some important Rust functions from librespot. Maybe look at the examples to decide what's needed.

Create functions that are callable from C as shown in this example.

Important: Wrap everything into a catch_unwind. If an error occurs, there might be UB if it reaches the border to C.

There are certainly some structs that need to be passed. Since those structs are not compatible with C, they must be passed as opaque type behind a pointer (as in the example).

Some functions are async. These functions must be executed by a tokio runtime. Create functions to created and destroy a tokio runtime. Return this runtime as opaque struct. (This struct could even be called librespot if the user shouldn't be bothered with implementation details.) For every function call that executes an async rust function, a pointer to this struct must be passed.

Remember, destructors in Rust are implicit. It's important to create functions that deallocate resources again, although these functions seem to do nothing. Look at the example above.

If it's ready, running cargo build will produce a .so file in target/debug.

Run cargo install cbindgen to install a tool to create a C header file. cbindgen --lang c will hopefully spit out the expected result.

You can now write a C application that uses librespot. Just include the header and link it against this .so file.

How does it sound?

Originally created by @Johannesd3 on GitHub (Apr 11, 2021). Original GitHub issue: https://github.com/librespot-org/librespot/issues/688 @d4rwel inspired me to write down some thoughts I had about creating C bindings for librespot. There's no need to change anything in librespot itself, it could happen in its own crate/repo. However, I assume that #665 is ready, but this could be accomplished with git dependencies. So here's a rough plan: Create a rust library crate and add the following to the `Cargo.toml`: ```toml [dependencies] librespot = "choose version" tokio = "choose version" [lib] crate-type = ["cdylib"] ``` Pick some important Rust functions from librespot. Maybe look at the examples to decide what's needed. Create functions that are callable from C as shown in [this example](https://gist.github.com/Johannesd3/2963d251945347de8988585d61e1e9b5). Important: Wrap everything into a [catch_unwind](https://doc.rust-lang.org/std/panic/fn.catch_unwind.html). If an error occurs, there might be UB if it reaches the border to C. There are certainly some structs that need to be passed. Since those structs are not compatible with C, they must be passed as opaque type behind a pointer (as in the example). Some functions are `async`. These functions must be executed by a [tokio runtime](https://docs.rs/tokio/1.4.0/tokio/runtime/struct.Runtime.html#method.block_on). Create functions to created and destroy a tokio runtime. Return this runtime as opaque struct. (This struct could even be called `librespot` if the user shouldn't be bothered with implementation details.) For every function call that executes an async rust function, a pointer to this struct must be passed. Remember, destructors in Rust are implicit. It's important to create functions that deallocate resources again, although these functions seem to do nothing. Look at the example above. If it's ready, running `cargo build` will produce a `.so` file in `target/debug`. Run `cargo install cbindgen` to install a tool to create a C header file. `cbindgen --lang c` will hopefully spit out the expected result. You can now write a C application that uses librespot. Just include the header and link it against this `.so` file. How does it sound?
kerem closed this issue 2026-02-27 19:30:22 +03:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/librespot#392
No description provided.