Reputation: 233
Rust code:
#[repr(C)]
pub struct Tmp {
pub callback: extern "C" fn(i: i32),
}
#[no_mangle]
pub extern "C" fn set_callback(callback: extern "C" fn(i: i32)) -> *mut Tmp {
let mut tmp = Box::new(Tmp { callback });
println!("tmp as ptr: {:p}", tmp); // >> here <<
&mut *tmp
}
#[no_mangle]
pub extern "C" fn use_callback(tmp_ptr: *mut Tmp) {
unsafe {
((*tmp_ptr).callback)(1);
((*tmp_ptr).callback)(3);
}
}
C++ code:
struct Tmp {
void (*callback)(int32_t);
};
typedef Tmp*(__stdcall* set_callback_t)(void(*callback_t)(int32_t));
typedef void(__stdcall* use_callback_t)(Tmp*);
void callback(int32_t i) {
printf("%d\n", i * 2);
}
int main() {
// ... loading rust part as .dll
// ... checking if loaded correctly
Tmp* tmp_ptr = set_callback(callback);
printf("tmp_ptr %p\n", tmp_ptr);
use_callback(tmp_ptr);
// ... freeing the .dll
}
When I compile this the program, it works as expected. The printed values of pointer to Tmp
structure in Rust and C++ match. When I comment out the println
in Rust, the C++ program crashes, which means that there is something wrong with this (probably Rust part) code.
I am using the Rust code as a .dll. I would like to pass a pointer to C++ function to the set_callback
function, and then I would like to use that pointer in the use_callback
function when I call use_callback
in the C++ code.
For what I understand, at the end I will have to call a Rust function to drop the Tmp
structure, but I left that out.
Upvotes: 2
Views: 807
Reputation: 29981
Box
in Rust is similar to std::unique_ptr
in C++. The way you construct tmp
, the data pointed to will be freed at the end of the function.
In order to "leak" the pointer into C++ world, you should use Box::into_raw
.
Note that as there is no guarantee that Rust and C++ allocate memory the same way; you will have to pass the pointer back to Rust and use Box::from_raw
to deallocate it.
Upvotes: 5