Skimming thru this thread... try this:
From C, call `PostLVUserEvent()`.
Then, in LabVIEW, rather than registering that event reference into a `Register for Events` node, register the event reference with a `Register Event Callback` node.
Here's the game-changer -- `PostLVUserEvent()` in C will behave differently depending on how the associated event reference is registered in LabVIEW.
When a listener is bound to the event using `Register for Events`, `PostLVUserEvent()` is asynchronous and non-blocking, and does not wait for the consumption of the event. It "blocks" only long enough to copy data reliably into the queue shared by its message-reference-counting registrants, then moves along.
On the other hand, `PostLVUserEvent()` will synchronously block until the Callback VI handler has finished executing.
This means, your library can `Post` some pointers/handles into LabVIEW, LabVIEW can fill them in the Callback VI, and downstream logic from the `PostLVUserEvent()` needs no further gymnastics to synchronize/mutex.