A
A
Andrey Kondratiev2016-02-14 11:13:47
Rust
Andrey Kondratiev, 2016-02-14 11:13:47

What is the best way to return a dynamic string from Rust via the C ABI: extern "C" fn myfunc()?

At first glance, you can do it as it is written in the book , but I have a question: how is memory allocated for the string in the example? Do I need to do free in the code that receives this line? I ask because I often have a part of the string in the recipient spoiled, especially if the string was long (maybe a defect on nightly).
I came up with some kind of stable working solution, but it somehow looks strange:
(the place under out is allocated in the C code that calls this function)

#[no_mangle]
pub extern fn rs_string_in_string_out(s_raw: *const c_char, out: *mut c_char) -> c_int {
    // take string from the input C string
    if s_raw.is_null() { return 0; }

    let c_str: &CStr = unsafe { CStr::from_ptr(s_raw) };
    let buf: &[u8] = c_str.to_bytes();
    let str_slice: &str = std::str::from_utf8(buf).unwrap();
    let str_buf: String = str_slice.to_owned();

    //produce a new string
    let result = String::from(str_buf + " append from Rust");
    let len = result.len();

    //create C string for output
    let c_result = CString::new(result);

    //write string into out pointer passed by C++ addon
    unsafe{ std::ptr::copy(c_result.unwrap().as_ptr(), out, len); };

    // return result length
    return len as c_int;
}

Answer the question

In order to leave comments, you need to log in

2 answer(s)
A
Andrey Kondratiev, 2016-02-25
@Andruhon

I don't know how new this is, but the documentation says that the libraries use alloc_system by default, which means that we can freely use free in C/C++.
Also, for peace of mind, you can add #![feature(alloc_system)] to the beginning of the file.

A
Alexander Orlov, 2016-02-15
@0x1B

I must say right away that I am only studying rust for the time being ...
Your solution is suspicious only in that you do not pass the size of the buffer allocated in the C-code to which out points to. If the s_raw string turns out to be too long, then when copying the result to out, an out-of-bounds buffer may occur. Therefore, the out parameter must also be passed the size of the memory it points to. Those. if len is greater than the size of the memory addressed to out, expect trouble.
The example from the book works only because a pointer to a string literal is returned - the memory for it is not released after exiting hello_rust. If you return a pointer to a variable allocated in rast, the memory will be freed and you can get unpredictable garbage in the C code.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question