0

I am trying to follow this stack overflow answer about casting, but it does not seem to work when I try to combine it with FnOnce:

use windows_sys::{
    Win32::System::Threading::*,
};

use std::os::raw::c_void;

pub struct Fiber {
    handle: *mut c_void,
    entry_point: Box<dyn FnOnce() -> ()>
}

impl Fiber {
    fn new<F>(entry_point: F) -> Result<Fiber, crate::PlatformError>
        where F: FnOnce() -> () + 'static
    {
        let mut entry_point_in_a_box = Box::new(entry_point);
        let entry_point_reference = &mut *entry_point_in_a_box;

        let handle = unsafe {
            CreateFiber(0, Some(fiber_entry_point),
            entry_point_reference as *mut _ as *mut c_void)
        };

        Ok(Fiber { 
            handle: handle,
            entry_point: entry_point_in_a_box
        })
    }
}

extern "system" fn fiber_entry_point(parameter: *mut c_void) {
    let entry_point: &mut dyn FnOnce() -> () = unsafe {
        &mut *(parameter as *mut dyn FnOnce() -> ())
    };
}

It instead gives me the following error:

error[E0277]: expected a `FnOnce<()>` closure, found `c_void`
  --> ████████.rs:33:16
   |
33 |         &mut *(parameter as *mut dyn FnOnce() -> ())
   |                ^^^^^^^^^ expected an `FnOnce<()>` closure, found `c_void`
   |
   = help: the trait `FnOnce<()>` is not implemented for `c_void`
   = note: wrap the `c_void` in a closure with no arguments: `|| { /* code */ }`
   = note: required for the cast to the object type `dyn FnOnce()`

What am I missing here?

user3840170
  • 22,750
  • 2
  • 21
  • 50
Rick de Water
  • 2,133
  • 2
  • 14
  • 30
  • 1
    You cannot case `*mut c_void` to `*mut dyn FnOnce()`, since the first is a thin pointer and the second is fat. You can cast `*mut c_void` to `fn()`, but you can't use `as` and need to use `transmute()`. – Chayim Friedman Jan 30 '22 at 11:05

0 Answers0