Has anyone tried this , does this really work ( playground)

#![crate_type = "cdylib"]

use std::ffi::{CStr, CString};
use std::os::raw::c_char;

/// Example function exported for C
#[no_mangle]
pub extern "C" fn hello_world() -> *mut c_char {
    CString::new("Hello, world!").unwrap().into_raw()
}

/// Free a string allocated by Rust
#[no_mangle]
pub extern "C" fn free_rust_string(s: *mut c_char) {
    if s.is_null() { return; }
    unsafe { CString::from_raw(s); }
}

(Playground)

Yes, this works.