0

I want to call C++ from Rust. C++ then allocates and fills a buffer, then Rust uses it and deallocates. However, I'd like to deliver back the function pointer to deallocate the data. This is what I tried:

In Rust:

extern "C" {
    pub fn openvpn_receive(
        instance: *mut OpenVpnInstance,
        size: *mut size_t,
        deallocate: extern "C" fn(*mut u8),
    ) -> *mut u8;
}

fn main() {
    let size: *mut size_t;
    let deallocate = extern "C" fn(*mut u8);
    let data: *mut u8 = openvpn_receive(self.instance, size, deallocate);
    //use data
    deallocate(data);
}

In C++:

uint8_t* openvpn_receive(size_t *size, void (*deallocate_function)(uint8_t *))
{
    deallocate_function = &cpp_deallocate_u8;
    uint8*t data = receive_data(size);
}

But the Rust code is not valid. How can I make such thing happen?

2
  • Your code is somewhat difficult to follow, since it contains several undeclared names (e.g. a reference to self in the middle of the main() function). It looks like your C++ function signature isn't right – it accepts a function pointer as an input, whereas you want to return a function pointer. You either need to make the deallocate function the return value, or accept a pointer to a function pointer, so you can write the function pointer to that memory location. Commented Nov 10, 2020 at 8:03
  • The Rust code also has some obvious errors. The declaration of deallocate should use a colon to separate name and type. The variable should be mutable, since you want to pass a mutable pointer to it to your C++ code. And the type should be unsafe extern "C" fn(*mut u8). Commented Nov 10, 2020 at 8:06

1 Answer 1

1

Maybe it will help You.

https://doc.rust-lang.org/std/keyword.extern.html

https://rust-embedded.github.io/book/interoperability/rust-with-c.html

C++ -> C -> Rust

use libc::{size_t, c_void};

#[repr(C)]
pub struct OpenVpnInstance();

//#[link(name = "your_c_library")]
extern "C" {
    pub fn openvpn_receive(
        instance: *mut OpenVpnInstance,
        size: *mut size_t,
        deallocate: *mut c_void,
    ) -> *mut u8;
}

pub fn my_callback(arg: *mut u8)
{
    println!("CB!");
}

fn main() 
{
    let size: size_t = 42;
    let instance = OpenVpnInstance{};
    
    let dummy_arg: u8 = 42;
    
    unsafe {
        let cb = my_callback as *mut c_void;
        let instance_ptr = &instance as *const _ as *mut OpenVpnInstance;
        let arg_ptr = &dummy_arg as *const _ as *mut u8;
        openvpn_receive(instance_ptr, size as *mut size_t, cb);
        my_callback(arg_ptr)
    }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.