{"id":18419899,"url":"https://github.com/vanjacosic/rust-ffi-to-c","last_synced_at":"2025-10-27T06:17:54.807Z","repository":{"id":60923618,"uuid":"544387568","full_name":"vanjacosic/rust-ffi-to-c","owner":"vanjacosic","description":"A simple tutorial on how to call a C function from Rust 🦀","archived":false,"fork":false,"pushed_at":"2024-02-05T14:25:17.000Z","size":16,"stargazers_count":116,"open_issues_count":1,"forks_count":15,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-22T19:12:20.853Z","etag":null,"topics":["c","ffi","rust","rust-ffi","rust-lang"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vanjacosic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-02T10:54:46.000Z","updated_at":"2025-03-21T08:33:56.000Z","dependencies_parsed_at":"2024-11-06T04:19:13.575Z","dependency_job_id":"10516a23-5492-43bf-8cda-ab9e7be8ca60","html_url":"https://github.com/vanjacosic/rust-ffi-to-c","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vanjacosic%2Frust-ffi-to-c","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vanjacosic%2Frust-ffi-to-c/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vanjacosic%2Frust-ffi-to-c/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vanjacosic%2Frust-ffi-to-c/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vanjacosic","download_url":"https://codeload.github.com/vanjacosic/rust-ffi-to-c/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247661795,"owners_count":20975118,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c","ffi","rust","rust-ffi","rust-lang"],"created_at":"2024-11-06T04:18:56.094Z","updated_at":"2025-10-27T06:17:54.719Z","avatar_url":"https://github.com/vanjacosic.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# How to call a C function from Rust 🦀☎️\n\nI was working on a Rust project where we needed to interact with code written in C.\n\nI had to learn how to work with FFI (Foreign Function Interface) in Rust and wrote up this little guide for others.\n\nThis repository is a working example of the final code from the tutorial I wrote below. Clone it and run it using `cargo run`.\n\n```bash\n$ cargo run\n   Compiling rust-ffi-to-c v0.1.0\n    Finished dev [unoptimized + debuginfo] target(s) in 0.93s\n     Running `target/debug/rust-ffi-to-c`\n\n[Rust] Hello from Rust! 🦀\n[Rust] Calling function in C..\n[C] Hello from C!\n[C] Input a is: 5000\n[C] Input b is: 5\n[C] Multiplying and returning result to Rust..\n[Rust] Result: 25000\n```\n\n## Tutorial\n\n### 1. Define an external function\n\nWe use [`extern`](https://doc.rust-lang.org/reference/items/external-blocks.html) to reference the `multiply()` function, which is written in C (`src/multiply.c`).\n\nIn this case we want to multiply integers, so we import a C-compatible integer type into Rust from `core:ffi`. (See all the [available types](https://doc.rust-lang.org/core/ffi/index.html))\n\nWe then define the argument types and return type for our C function as `c_int` (equivalent to `i32` in Rust).\n\n```rust\nextern crate core;\nuse core::ffi::c_int;\n\nextern \"C\" {\n    fn multiply(a: c_int, b: c_int) -\u003e c_int;\n}\n```\n\n### 2. Call the C function from Rust\n\nAny use of foreign function is considered unsafe because the Rust compiler can't guarantee memory safety in foreign code. \nSo in our main Rust file (`src/main.rs`) we call the function in an `unsafe` block, then pass in two `i32` integers, and print the result.\n\n```rust\nunsafe {\n    println!(\"Result: {}\", multiply(5000, 5));\n}\n```\n\n### 3. Compile and run\n\nFirst we compile our `multiply.c` file using a C compiler:\n\n    clang src/multiply.c -c\n\nThe `-c` flag tells the C compiler to output a \"object file (`.o`)\" instead of an executable program. So it creates a `multiply.o` file that we can use as a shared dynamic library in our Rust code.\n\nSecond we create a static library file libmultiply.a using the ar tool:\n\n    ar rcs libmultiply.a multiply.o\n\nThen we compile our program using the Rust compiler:\n\n    rustc src/main.rs -l multiply -L .\n\nThe `-l multiply` option tells the Rust compiler to link the shared library.\nThe `-L .` option tells the Rust compiler to look for libraries in the current directory.\n\nThe compiler creates an executable named `main` which we can run:\n\n    ./main\n    [Rust] Hello from Rust! 🦀\n    [Rust] Calling function in C..\n    [C] Hello from C!\n    [C] Input a is: 5000 \n    [C] Input b is: 5 \n    [C] Multiplying and returning result to Rust..\n    [Rust] Result: 25000\n\n### 4. Automate 🤖\n\nIt gets tedious to compile the files manually every time, so we will use cargo build script and the [`cc`](https://crates.io/crates/cc) crate to automate this process.\n\nAdd `cc` to the projects build dependencies:\n\n```toml\n[build-dependencies]\ncc = \"1.0\"\n```\n\nCreate a `build.rs` and add compile instructions:\n\n```rust\nextern crate cc;\n\nfn main() {\n    cc::Build::new().file(\"src/multiply.c\").compile(\"multiply\");\n}\n```\n\nAnd now we can use Cargo to build both the C and Rust code and run the program:\n\n    cargo run\n\n\n## Notes\n\n- From [Rust 1.64.0](https://blog.rust-lang.org/2022/09/22/Rust-1.64.0.html#c-compatible-ffi-types-in-core-and-alloc) it is now recommended to use `core::ffi` instead of `std::os::raw` to access C types. The latter is now an alias to types in the `core::ffi` module. `core` is also available in places where the Rust standard library (`std`) is not, like [embedded projects](https://docs.rust-embedded.org/book/intro/no-std.html).\n\n- Mapping out functions manully using `extern` is fine for small projects, but as soon as you are dealing with a bigger library or codebase, you want to take a look at `bindgen`. It can automatically generate the bindings for C or C++ libraries, making using them in Rust a lot easier. See [the `bindgen` User Guide](https://rust-lang.github.io/rust-bindgen/).\n\n- We can control how our code is linked using the [`#[link()]` attribute.](https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute). It allows us to specify or rename functions and change the type of linking to use, eg. to static:\n\n    ```rust\n    #[link(name = \"multiply\", kind = \"static\")]\n    extern \"C\" { // ... }\n    ```\n\n## Further reading\n\n- [FFI chapter in The Rustonomicon book](https://doc.rust-lang.org/nomicon/ffi.html) (Rustonomicon is the official guide to unsafe Rust)\n\n- [FFI chapter in the Secure Rust Guidelines book](https://anssi-fr.github.io/rust-guide/07_ffi.html)\n\n- [\"A little C with your Rust\" chapter in The Embedded Rust Book](https://docs.rust-embedded.org/book/interoperability/c-with-rust.html) (The official Embedded Rust guide)\n\n- [A Guide to Porting C and C++ code to Rust](https://locka99.gitbooks.io/a-guide-to-porting-c-to-rust/content/)\n\n- [Build Scripts - The Cargo Book](https://doc.rust-lang.org/cargo/reference/build-scripts.html)\n\n- [Deciphering Rust’s `#[no_mangle]` - pwnthebox.net](https://web.archive.org/web/20221113090341/https://www.pwnthebox.net/rust/2020/11/01/deciphering-no-mangle.html)\n\n- [Rust FFI: Sending strings to the outside world | Huy's Blog](https://web.archive.org/web/20221007224430/https://snacky.blog/en/string-ffi-rust.html)\n\n- [The Rust FFI Omnibus](http://jakegoulding.com/rust-ffi-omnibus/)\n\n- 📖 Chapter 11: *\"Foreign Function Interfaces\"* in [Rust for Rustaceans](https://nostarch.com/rust-rustaceans) by Jon Gjengset\n\n- 📖 Chapter 23: *\"Foreign Functions\"* in [Programming Rust, 2nd Edition](https://www.oreilly.com/library/view/programming-rust-2nd/9781492052586/) by Jim Blandy, Jason Orendorff \u0026 Leonora F. S. Tindall\n\n## Further watching\n\n- [Crust of Rust: Build Scripts and Foreign-Function Interfaces (FFI)](https://www.youtube.com/watch?v=pePqWoTnSmQ)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvanjacosic%2Frust-ffi-to-c","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvanjacosic%2Frust-ffi-to-c","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvanjacosic%2Frust-ffi-to-c/lists"}