'Create a safe binding between C and Rust for non opaque datatypes passed as *void

I need to interface with a third party C library where I have a function like this:

void setOption(const char* optionName, void* value) {
  if (strcmp(optionName, "OPTION_1") == 0) {
    gOption1 = (const uint_fast64_t) value;
  } else if(strcmp(optionName, "OPTION_2") == 0) {
    gOption2 = (char*)value;
  } else if(strcmp(optionName, "OPTION_3") == 0) {
    gOption3 = *(uint32_t*)value;
  } 
}

How can I be sure that the types are correctly represented in Rust, so that they can be properly read in C? The only way I have found is to expose the implementation of the library to the Rust code, so creating a different function for each option.

The corresponding Rust binding I wrote is:

extern {
    pub fn setOption(optionName: *const u8, value: *mut c_void); 
}

And the wrapper only for u32 for conciseness:

pub fn set_option3(value: u32) {
     let name = "OPTION_3";
     let value_boxed : Box<u32> = Box::new(value);
     let value_u32_ptr : *mut u32 = Box::into_raw(value_boxed);
     unsafe {
         setOption(name.as_ptr() as *const u8, value_u32_ptr as *mut c_void );
     }
 }

Then used from Rust as:

fn main() {
     let val : u32 = 178;
     set_option3(val);
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source