Introduction
Rust is renowned for its performance and safety, but it also plays well with other languages through its Foreign Function Interface (FFI). In this blog post, we'll explore how to integrate Rust with other languages by creating bindings. We'll use Rust to create a library and then call this library from C and Python.
Creating a Rust Library
First, we'll create a Rust library that provides some basic functionality.
Set Up Your Rust Project
Create a new Rust library project:
cargo new --lib rust_ffi_example
cd rust_ffi_exampleWrite Rust Code
Open src/lib.rs and add the following code:
// src/lib.rs
#[no_mangle]
pub extern "C" fn add(a: i32, b: i32) -> i32 {
a + b
}
#[no_mangle]
pub extern "C" fn greet(name: *const libc::c_char) {
let c_str = unsafe {
assert!(!name.is_null());
std::ffi::CStr::from_ptr(name)
};
let r_str = c_str.to_str().unwrap();
println!("Hello, {}!", r_str);
}Here, we've defined two functions:
add: Adds two integers and returns the result.greet: Prints a greeting message using a string passed from C.
Configure Cargo for FFI
Edit Cargo.toml to add the following configuration:
[lib]
name = "rust_ffi_example"
crate-type = ["cdylib"]This tells Cargo to build a C dynamic library.
Build the Rust Library
Compile the Rust library:
cargo build --releaseThe output will be a shared library file (librust_ffi_example.so, librust_ffi_example.dylib, or rust_ffi_example.dll depending on your OS) in the target/release directory.
Using the Rust Library in C
Now let's use the Rust library in a C program.
Write a C Program
Create a new directory and add a C file, main.c:
// main.c
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "rust_ffi_example.h"
int main() {
int result = add(5, 3);
printf("5 + 3 = %d\n", result);
const char *name = "Rust";
greet(name);
return 0;
}Create a Header File for the Rust Library
Create a header file, rust_ffi_example.h:
// rust_ffi_example.h
#ifndef RUST_FFI_EXAMPLE_H
#define RUST_FFI_EXAMPLE_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
int32_t add(int32_t a, int32_t b);
void greet(const char *name);
#ifdef __cplusplus
}
#endif
#endif // RUST_FFI_EXAMPLE_HCompile and Link the C Program
Compile and link the C program with the Rust library:
gcc main.c -L./target/release -lrust_ffi_example -o mainRun the program:
./mainUsing the Rust Library in Python
Let's use the Rust library in a Python program using ctypes.
Write a Python Script
Create a Python script, main.py:
# main.py
import ctypes
import os
# Load the Rust library
lib_path = os.path.join(os.path.dirname(__file__), 'target', 'release', 'librust_ffi_example.so')
rust_lib = ctypes.CDLL(lib_path)
# Define argument and return types
rust_lib.add.argtypes = [ctypes.c_int, ctypes.c_int]
rust_lib.add.restype = ctypes.c_int
rust_lib.greet.argtypes = [ctypes.c_char_p]
rust_lib.greet.restype = None
# Call the Rust functions
result = rust_lib.add(10, 20)
print(f"10 + 20 = {result}")
name = b"Rust"
rust_lib.greet(name)Run the Python Script
Make sure you have the shared library file in the correct path and run the script:
python3 main.pyConclusion
In this blog post, we demonstrated how to integrate Rust with other languages using FFI. We created a Rust library, built it, and used it from both C and Python. Rust's FFI capabilities make it possible to leverage Rust's performance and safety while interacting with code written in other languages.
Feel free to experiment with other languages and libraries, and explore the powerful interoperability that Rust offers!
