// C declaration
int32_t test(int32_t x);
// Rust
#[no_mangle]
pub extern fn test(x: i32) -> i32 {
x * 3
}
// Swift
let a: Int32 = test(10) // a == 30
// C declaration
void hello(const char* s)
// Rust
use std::os::raw::c_char;
#[no_mangle]
pub unsafe extern "C" fn hello(s: *const c_char) {
let str = CStr::from_ptr(s).to_string_lossy().into_owned();
...
}
// Swift
hello("World")
// C declaration
const char* hello()
// Rust
use std::os::raw::c_char;
#[no_mangle]
pub unsafe extern "C" fn hello() -> *const c_char {
CString::new("World").unwrap().into_raw();
}
// Swift
let cString = hello()
let s = String(cString: cString) // "World"
pub fn into_raw(self) -> *mut c_char
Consumes the CString and transfers ownership of the string to a C caller.
The pointer which this function returns must be returned to Rust and reconstituted using from_raw to be properly deallocated.
...
// C declaration
void cstr_free (const char* s);
// Rust
#[no_mangle]
pub unsafe extern "C" fn cstr_free(s: *mut c_char) {
CString::from_raw(s);
}
// Swift
let cString = hello() // cString: UnsafePointer<Int8>
let s = String(cString: cString) // "World"
cstr_free(cString)
📦 also has into_raw
and from_raw
, but you
can not access the data inside the 📦 from Swift directly.
// Rust
pub struct Meetup { data: Vec<i32> }
#[no_mangle]
pub extern fn meetup_new() -> *mut Meetup {
let data = Meetup{ data: vec![1, 2, 3, 4, 5] };
Box::into_raw(Box::new(data))
}
pub extern fn meetup_count(meetup: *const Meetup) -> size_t {
let meetup = unsafe { &*meetup };
meetup.data.len() as size_t
}
// C declaration
struct meetup;
struct meetup *meetup_new(void);
size_t meetup_count(const struct meetup *data);
// Swift
let raw = meetup_new()
meetup_count(raw) // 5
Because I'm writing a wallet for cryptocurrency written in Rust and I do not want to reimplement blockchain myself.