Cast c_int to *mut c_void

I have C function:

fn my_func(p_arg : *mut c_void);

I would like pass a parameter to function:

let val : c_int = 0;
let p_val = val as *mut c_void;
if p_val == ptr::null_mut() {
    println!("TEST p_val is nullptr");
}

but parameter after cast is nullptr - why?
How to fix?

Here, val is an integer, and integers are cast to pointers by treating the integer as an address (reference). That's why you end up with nullptr.

The fix is also straightforward — cast a reference to a pointer instead:

let p_val = &mut val as *mut c_void;

Apparently, you need to mark val as mut to do this.

Demonstration on the playground:

fn main() {
    let mut val = 0;
    
    println!("{:p}",      val as *mut i32); // null pointer
    println!("{:p}", &mut val as *mut i32); // the address of the variable
}
1 Like

@L.F

error[E0606]: casting `&mut i32` as `*mut std::ffi::c_void` is invalid
  --> src/lib.rs:72:29
   |
72 |                 let p_val = &mut val as *mut c_void;

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=13b6373cadaddc2cd02b40f17e1d82a1

You need to cast the reference to a *mut c_int before casting to *mut c_void. To retrieve the value from the *mut c_void, you need to cast it to a *const c_int first (*mut c_int works too), and then dereference it (which is an unsafe operation):

use libc::c_int;
use libc::c_void;

fn main() {
    let mut val : c_int = 0;
    
    let p_val = &mut val as *mut c_int as *mut c_void;

    println!("ptr: {:p}", p_val);
    println!("value: {:}", unsafe { *(p_val as *const c_int) });
}

(playground)

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.