Hi!
I'm new to rust and intrigued by the potential it seems to have for working with strings. My first hands-on experience is thanks to this fine gentleman's efforts. Here is the relevant module. He demonstrates how you can pass a string from Swift to Rust and get the levenshtein index.
I wonder what the best way is to pass an entire array of strings to do something with it in Rust. However, I am stopped short with not FFI-safe
warnings. I tried a few things like defining something like a StringBridge struct, but that doesn't seem to solve the Sized
conformance issues - and from what I've seen it's not as simple as extending my struct by declaring conformance and then implementing whatever is necessary for the struct to conform, or is there a way to do this? (Like one would do in Swift by conforming to Hashable
or ExpressibleByFloatLiteral
or w/e.)
I've been hacking my way through to something that's obviously stupid, but should illustrate what I mean. Interestingly, here the compiler gives me the not FFI-safe
warning, too, but I can call it from Swift nevertheless.
use std::ffi::CStr;
use std::os::raw::{c_char, c_double, c_long};
#[no_mangle]
pub extern "C" fn leven_loop_feeding_through_callback(indices: c_long, callback: fn(&c_long) -> *const c_char) -> c_double {
let strings: Vec<String> = (0..indices)
.into_iter()
.map(|idx| unsafe { CStr::from_ptr(callback(&idx)) }.to_str().unwrap().to_string())
.collect();
// Do whatever
let mut sum: f64 = 0.0;
for _ in 0..2500 {
for word in &strings {
for other in &strings {
let count_sum = (word.len() + other.len()) as f64;
let dist = levenshtein::levenshtein(&word, &other) as f64;
sum += (count_sum-dist)/count_sum;
}
}
}
return sum
}
From Swift:
let mock: [String] = ["hello", "bonjour", "hola", "hallo"]
let sum: Double = leven_loop_feeding_through_callback(mock.count) { ptr -> UnsafePointer<Int8>? in
let mockAgain: [String] = ["hello", "bonjour", "hola", "hallo"]
let index: Int = ptr!.pointee
let cString: [CChar] = mockAgain[index].cString(using: .utf8)!
return UnsafePointer<Int8>(cString) // dangling pointer warning
}
Is the entire approach flawed (wanting to pass in String-Arrays) and should I thus consider a different one? If you have pointers to stuff that helps me understand this better, that would be great! Do you know about good resources that address common challenges with bridging? The compiler also suggests to consider using a raw pointer instead
, how would one do that given an array of strings?