0

There's a function:

pub fn vigem_target_add_async(
        vigem: PVIGEM_CLIENT,
        target: PVIGEM_TARGET,
        result: PFN_VIGEM_TARGET_ADD_RESULT,
    ) -> VIGEM_ERROR; 

where PFN_VIGEM_TARGET_ADD_RESULT is a callback type:

pub type PFN_VIGEM_TARGET_ADD_RESULT = ::std::option::Option<unsafe extern "C" fn(EVT_VIGEM_TARGET_ADD_RESULT)>;

Can I do with async/await something like:

vigem_target_add_async(vigem, target, FUNC::BOILERPLATE_FUTURE).await

And get EVT_VIGEM_TARGET_ADD_RESULT?

E_net4
  • 27,810
  • 13
  • 101
  • 139
DuckerMan
  • 105
  • 1
  • 1
  • 5

1 Answers1

0

The easiest way to do that is with a oneshot channel:

use futures::channel::oneshot;

let (send, recv) = oneshot::channel::<EVT_VIGEM_TARGET_ADD_RESULT>();

vigem_target_add_async (vigem, target, |r| send.send (r).unwrap());
let result = recv.await;
Jmb
  • 18,893
  • 2
  • 28
  • 55
  • It wont work, because `PFN_VIGEM_TARGET_ADD_RESULT` is function, not a closure – DuckerMan May 11 '20 at 14:05
  • Does `PFN_VIGEM_TARGET_ADD_RESULT` accept a "user data" parameter? If yes, you use that to pass `send`. If not, its API is broken and there is no clean way to use it in asynchronous code (including multi-thread) in any language. In that case, you will need to use some global variable to store `send` and make sure that it is never called in parallel. – Jmb May 11 '20 at 14:38
  • No, it does not support user data – DuckerMan May 11 '20 at 14:39
  • Then you can still use a `oneshot` channel, but you will need to put the `send` part in a global variable so that your callback can access it. See [this answer](https://stackoverflow.com/a/27826181/5397009) for ways to make a mutable global variable in Rust. – Jmb May 11 '20 at 14:56
  • You will also need to make sure that there is never more than one call to `vigem_target_add_async` active simultaneously to avoid conflicting accesses to the global variable. – Jmb May 11 '20 at 14:58