So I’ve been playing around with Rust in my spare time for a few months now, and have been doing a lot of stuff that bridges C/C++ and Rust content. And one thing that has always bugged me is that I can use a super awesome allocator like jemalloc in Rust, but that the allocations being done via C++ were not being routed into this allocator. So as a tiny baby step into the Rust community, I’ve released my first crate cpp_new. This crate simply maps C++’s new/delete/new/delete via extern “C” functions back into Rust’s global allocators.
To use, you simply do:
And Rust will take care of the rest. This allows you to map any C++ allocations in existing content into a single allocator across your C++ and Rust content!
How It Is Implemented⌗
To implement the crate there are two source files, the first being lib.rs which contains two functions rust_cpp_new and rust_cpp_delete. Rust’s global allocators use a Layout to allocate memory. A layout is effectively a struct with two usize’s in it - one is the size of the memory and the other is the alignment. This is fine for rust_cpp_new, because we can pass this information from the C++ side. But it becomes slightly trickier for rust_cpp_delete, because C++ only provides us with a void* of the ‘memory to free', but Rust expects an identical layout that was used to create the memory to delete it.
To get around this, we don’t just allocate the memory as was requested by the user, we also fudge on a little blob of memory just before the allocation we return to the user that contains the Layout.
While this looks a little confusing - all we are doing is making room for the Layout and storing it. Now when we are freeing memory we need to be careful to undo the fudge and get to the start of the Layout instead of the start of the user provided pointer:
And that’s it! Now the second file is new.cpp - which contains the definitions of C++’s new/delete/new/delete.
For both the single-object and array we use the same Rust methods. We also have no information on the alignment requirements so we need to choose some value. I’ve chosen 16 bytes alignment because that is the alignment that stackoverflow told me some C++ implementations use. It at least covers all the base use cases, and since Layout is two usize’s (and thus 16 bytes itself) it means we’ve got no wasted bytes in the allocation.
This crate is super simple, super easy to use, and was a nice introduction to how to package up a Rust crate for use. The crate is provided under the CC0 1.0 Universal public domain and permissible license, and I hope it proves useful to someone!