Non-allocating C string getters

Looking at e.g. String Return Values - The Rust FFI Omnibus

I'd like to be able to have const char *foo_struct_get_some_string (FooStruct*foo) that doesn't allocate, where FooStruct is defined in Rust.

First, I'd like to just hard assume that Rust uses malloc, so I don't need to export separate free functions. That's a even easier now with System in std::alloc - Rust though AIUI since we're building our Rust code as a static library it's the default.

Now, for avoiding allocating string copies - would using CString in our Rust structures be a best practice here? I'm looking at what Firefox does, although there's obviously quite a lot of code there.

If you also want to have str like properties on the Rust side, I think you need a type that combines guarantees of both string kinds: valid UTF-8 and trailing NUL without embedded NULs. Then they can deref to &str and you can also hand out pointers to the C side.

Such a type might already exist on crates.io.

I'm not sure if Rust gives a guarantee that you can call free() on anything Rust-allocated, even if Rust uses system allocator.

If you want C to call free, it's best to use libc::malloc yourself.

1 Like

I should have thought to search crates, doing so now turns up at least https://crates.io/crates/terminated which looks exactly like what I want.

The code looks sane, though the fact that there are zero reverse dependencies though makes me hesitate. Anyways I'll try it out.

Is anyone aware of a good reference for a codebase doing nontrivial FFI between Rust and C?

Iā€™m not sure if Rust gives a guarantee that you can call free() on anything Rust-allocated, even if Rust uses system allocator.

Can someone comment authoritatively one way or the other? From my reading of the docs it seems like it's strongly implied, and looking at the source:

        #[inline]
        unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
            libc::free(ptr as *mut libc::c_void)
        }

Right?

It is probably best to avoid having free in a difference code base than alloc. Even though explicit free functions add extra headache to codding. It maybe making your code brittle.

Only whispers of advice I have read from others rather than from a definitive source. My quick search just now brings up this;
"loaded dynamic-link libraries (DLLs) may create and use separate heaps"

1 Like

Cross-linking https://www.reddit.com/r/rust/comments/9ibr9s/passing_a_string_to_c_efficiently/