

Este projeto demonstra como integrar código escrito em Rust com aplicações desenvolvidas em Java, Python e Node.js utilizando Foreign Function Interface (FFI). O objetivo é mostrar que é possível introduzir Rust de forma incremental em sistemas existentes, aproveitando seu desempenho e segurança sem substituir toda a base de código.
Cada exemplo ilustra como compilar uma função Rust como uma biblioteca nativa e chamá-la diretamente a partir de outra linguagem. Embora as ferramentas utilizadas sejam diferentes, o princípio subjacente é o mesmo: comunicação entre linguagens por meio de interfaces nativas.
O projeto está organizado em três diretórios principais, cada um contendo um exemplo de integração com uma linguagem diferente:
Cada diretório contém os arquivos-fonte necessários e pode ser construído independentemente.
Este exemplo mostra como chamar uma função Rust a partir de uma aplicação Java usando a JNI (Java Native Interface). A função Rust calcula o fatorial de um número inteiro.
public class Calculator {
static {
System.loadLibrary("rust_jni_demo");
}
public native long factorial(int n);
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println(calc.factorial(10));
}
}
A linha System.loadLibrary("rust_jni_demo") carrega a biblioteca nativa compilada a partir do código Rust. O método factorial é declarado como native, indicando que sua implementação está em código nativo.
use jni::objects::JObject;
use jni::sys::{jint, jlong};
use jni::JNIEnv;
#[no_mangle]
pub extern "system" fn Java_Calculator_factorial(
_env: JNIEnv,
_this: JObject,
n: jint
) -> jlong {
if n < 0 {
return 0;
}
if n > 20 {
return 0;
}
let mut acc: i64 = 1;
for i in 1..=n as i64 {
acc = acc.saturating_mul(i);
}
acc as jlong
}
A função Rust é exportada com #[no_mangle] para preservar o nome e seguir a convenção de chamada C. O nome da função Java_Calculator_factorial segue a convenção JNI: Java_ + nome da classe + nome do método. Ela recebe parâmetros compatíveis com tipos C e retorna um valor nativo.
Calculator.h com o comando javac -h . Calculator.java.cargo build --release.java -cp . -Djava.library.path=target/release Calculator
Este exemplo demonstra como criar uma extensão Python em Rust usando a biblioteca PyO3. A função fibonacci é escrita em Rust, mas pode ser chamada como se fosse uma função Python nativa.
use pyo3::prelude::*;
#[pyfunction]
fn fibonacci(n: u32) -> PyResult<u64> {
if n > 93 {
return Err(pyo3::exceptions::PyValueError::new_err(
"Fibonacci(n) is too large for u64 when n > 93"
));
}
match n {
0 => Ok(0),
1 => Ok(1),
_ => {
let mut a = 0u64;
let mut b = 1u64;
for _ in 2..=n {
let temp = a.checked_add(b)
.ok_or_else(|| pyo3::exceptions::PyOverflowError::new_err("u64 overflow"))?;
a = b;
b = temp;
}
Ok(b)
}
}
}
#[pymodule]
fn pyrust_demo(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(fibonacci, m)?)?;
Ok(())
}
A macro #[pyfunction] marca a função fibonacci para exportação ao Python. O módulo pyrust_demo é o ponto de entrada carregado pelo interpretador Python. O uso de PyResult permite retornar erros compatíveis com exceções do Python.
from pyrust_demo import fibonacci
print(fibonacci(30)) # Output: 832040
print(fibonacci(94)) # Raises ValueError
Eu sugeriria criar um venv antes de mais nada:
python -m .venv
source .venv/bin/activate
Mas você é quem sabe!
maturin: pip install maturin ou pip install -r requirements.txt.maturin develop
python test.py
Não precisa compilar o projeto Rust em separado.
Este exemplo mostra como criar um addon para Node.js usando napi-rs, que permite escrever extensões nativas em Rust com suporte a N-API, garantindo compatibilidade entre versões do Node.js.
use napi_derive::napi;
#[napi(js_name = "reverseString")]
pub fn reverse_string(s: String) -> String {
s.chars().rev().collect()
}
A macro #[napi] exporta a função para o ambiente Node.js. O atributo js_name define como a função será exposta no JavaScript. O tipo String é automaticamente convertido entre Rust e JavaScript.
const { reverseString } = require('./addon.js');
console.log(reverseString('hello'));
O módulo addon.js é gerado durante a compilação e atua como um wrapper para o binário nativo.
npm install
npm build run
node index.js
Todos os exemplos demonstram o mesmo conceito central: Rust pode ser integrado a sistemas existentes por meio de interfaces nativas. Apesar das diferenças nas ferramentas — JNI, PyO3, napi-rs — o padrão é consistente:
Essa abordagem permite migrações graduais, onde componentes críticos de desempenho são reescritos em Rust, enquanto o restante do sistema permanece funcional.
Este modelo é amplamente utilizado em produção para melhorar eficiência, segurança e confiabilidade sem interromper serviços existentes. ```