I'm trying to pass a string from luajit to rust and return a new string but have been unable to get it to work fully. I also suspect the code will have plenty of room for improvement. Help with this would be greatly appreciated!
I've looked at rust-ffi-examples/luajit-to-rust/src at master · alexcrichton/rust-ffi-examples · GitHub and Returning an owned string · Issue #2 · shepmaster/rust-ffi-omnibus · GitHub for inspiration.
My incomplete implementation looks like this right now:
# Rust
extern crate libc;
use libc::c_char;
use std::ffi::CStr;
use std::str;
#[no_mangle]
pub extern fn greet_from_rust(subject_c_ptr: *const c_char) -> *const u8 {
let subject_c = unsafe {
assert!(!subject_c_ptr.is_null());
CStr::from_ptr(subject_c_ptr)
};
let subject = str::from_utf8(subject_c.to_bytes()).unwrap();
let mut new_string: String = "hey, ".to_owned();
new_string.push_str(subject);
new_string.shrink_to_fit();
let new_string_ptr = new_string.as_ptr();
std::mem::forget(new_string);
return new_string_ptr;
}
-- lua
local ffi = require "ffi"
ffi.cdef [[
const char* greet_from_rust(const char* subject);
]]
local greet_from_rust = ffi.load('../rust/target/release/libgreet_from_rust.so').greet_from_rust
local result = greet_from_rust("peter")
local greeting = ffi.string(result, 9)
print(greeting) -- successfully prints "hey, peter"
However, I was not able to replace the return type *const u8
with *const c_char
and lua does not know of the length of the new string. Maybe we could introduce a struct with two members, the string and its length?
Also, who now owns new_string? Do luajit and its GC dispose of it later?
Can we make this code any faster by not copying everything, but working on the C string/char* directly?