I need to perform a series of read/write tasks inside a ctypes callback function, but still inside an async task that is responsible for giving such read/write tasks:
async def main(ble_address):
async with BleakClient(ble_address) as client:
def my_io_callback(...)
# await client.read_gatt_char(UUID) ???
# await client.write_gatt_char(UUID, ...) ???
my_c_function(to_c_function(my_io_callback))
asyncio.run(main(ble_address))
I can't move the whole async block inside the callback because it will be called several times and I need the device to be connected during the entire interaction.
What's the proper way of dealing with this situation? Answers I've seen so far haven't quite cover this particular case.
Without knowing the fine details of your code it is possible that the following is a solution:
I would call an async function from a sync functions using the run_coro
function below. The first time this function is called, it creates a new daemon thread running an event loop and then uses asyncio.run_coroutine_threadsafe
to run the async function in the new thread:
import asyncio
import threading
_event_loop = None
def run_async(coro):
"""await a coroutine from a synchronous function/method."""
global _event_loop
# Lazily create a new event loop and a daemon thread that will run it:
if not _event_loop:
_event_loop = asyncio.new_event_loop()
threading.Thread(target=_event_loop.run_forever, name="Async Runner", daemon=True).start()
return asyncio.run_coroutine_threadsafe(coro, _event_loop).result()
async def main():
sync_function() # call a sync function
def sync_function():
# We want to await an async_function, so:
result = run_async(async_function())
print(result)
async def async_function():
await asyncio.sleep(1)
return 7
asyncio.run(main())
Prints:
7
Note that the call to run_coro
will block the main thread until the async function being invoked completes. But you stated in one of your comments:
Unfortunately this is impossible because the c callback (third party library) is supposed to block until the end of the IO operation.
So this blocking behavior should be exactly what you want.