Возврат строки из функции Rust для вызова с FFI

Я хочу, чтобы интерпретируемый язык (в частности, LuaJIT) вызывал функцию Rust, возвращающую строку.

То, что у меня происходит, вылетает еще до того, как я разыменую указатель.

Я читал, что строки Rust не заканчиваются нулем, поэтому я использую функцию to_c_str(), чтобы создать строку, которая есть, но я полагаю, что время жизни каким-то образом мешает всему этому, поскольку я все еще немного не уверен в них.

Код ржавчины:

#![crate_type = "dylib"]

extern crate libc;

#[no_mangle]
pub extern "C" fn hello_world() -> std::c_str::CString {
    "Hello World".to_c_str()
}

Код Lua:

local ffi = require("ffi")
ffi.cdef[[
char *hello_world();
]]

local hello_world = ffi.load("hello_world")
local hw = hello_world.hello_world()

person JonathanDHope    schedule 26.10.2014    source источник


Ответы (2)


CString - это не только указатель; это указатель плюс логическое значение, указывающее, CString владеет строкой C. Из-за этого объявление в вашем коде Lua не соответствует определению в вашем коде Rust.

Верните *const c_char или *mut c_char с помощью метода unwrap на CString. Если ваша функция возвращает динамически выделяемую строку, вам также необходимо предоставить функцию для освобождения строки, которую код Lua должен вызывать вручную, иначе это вызовет утечку памяти.

person Francis Gagné    schedule 26.10.2014
comment
Сработало отлично. Спасибо! - person JonathanDHope; 26.10.2014

Ответ Фрэнсиса Гагне верен. Вот полное рабочее решение.

Код ржавчины:

#![crate_type = "dylib"]

extern crate libc;

#[no_mangle]
pub extern "C" fn hello_world() -> *const libc::c_char {
    unsafe { "Hello World".to_c_str().unwrap() }
}

Код Lua:

local ffi = require("ffi")
ffi.cdef[[
char *hello_world();
]]

local hello_world = ffi.load("hello_world")
local hw = ffi.string(hello_world.hello_world())
person Community    schedule 16.09.2016