Let's say I have a rust object, and I want to pass ownership of that object outside of rust. I want to then allow the external interface to call back into a rust function that changes the object, and then eventually get back ownership in the rust layer.
I am thinking the following approach:
// this can be called multiple times when the c layer has ownership,
// but never twice at the same time
fn rust_function(ptr: *mut c_void) {
let rust_object = Box::leak(Box::from_raw(ptr as *mut RustObject));
// now we can preform operations on rust_object that modify it
}
fn main() {
let rust_object_ptr = Box::into_raw(Box::new(RustObject::new()));
// calls c code that will call back into rust using `rust_function`.
preform_external_operations(rust_object_ptr as *mut c_void, rust_function);
// now i have ownership of my rust object back
let rust_object = Box::from(rust_object_ptr);
}
Looking for clarification if this is sane, and if there might be a better way. Thanks in advance!
Since managing the lifetime of RustObject is fully on Rust side (you never actually give up ownership – your main function is destroying the object, not C code), there's no need to box anything at all. Also, I think that all pointers (and references) have compatible ABI, so rust_function can just take &mut RustObject.
extern "C" fn rust_function(ptr: &mut RustObject) {
// now we can preform operations on rust_object that modify it
}
fn main() {
let mut rust_object = RustObject::new();
// calls c code that will call back into rust using `rust_function`.
preform_external_operations(
(&mut rust_object) as *mut RustObject as *mut c_void,
rust_function
);
}
Please also note that you need extern "C" declaration on all C-callable functions, because there's no guarantee that rust's calling convention is the same as C's.
Please also note that you need extern "C" declaration on all C-callable functions, because there’s no guarantee that rust’s calling convention is the same as C’s.
Yup! I was trying to simplify the example (the library has it set up so that you can pass a safe funtion, and the extern "C" fn calls the safe function) , thanks though!