ronaldoussoren / pyobjc

The Python <-> Objective-C Bridge with bindings for macOS frameworks
https://pyobjc.readthedocs.io
560 stars 47 forks source link

Starting 'runConsoleEventLoop' from a secondary thread. #215

Closed ronaldoussoren closed 6 years ago

ronaldoussoren commented 6 years ago

Original report by WayneK (Bitbucket: WayneK, GitHub: WayneK).


Hi,

First, thanks for a extremely useful library, kudos.

I have a CoreBluetooth based BLE advertisement scanner working with PyObjc all ok. As I am putting this into a (multi-platform) Python module and I would like the main loop to be kicked off from a secondary thread created by the library, so to stay out of the way of users code.

In order to start the RunLoop using 'AppHelper.runConsoleEventLoop' on a thread I have created an Autorelease pool within the thread but am not receiving Bluetooth events.
I /think/ I need to create and pass a new dispatch queue to 'CoreBluetooth.CBCentralManager.initWithDelegate_queueoptions' created within the same thread, the but PyObjC doesn't support dispatch_queue_t yet.

I've read that starting a runloop on a secondary thread /should/ be possible.. is it really true for Objc? is it really possible in PyObc C ?

Do I really need a dispatch_queue_t? Is there an rough estimate as to when it will be added?

Thanks, Wayne

ronaldoussoren commented 6 years ago

Original comment by Ronald Oussoren (Bitbucket: ronaldoussoren, GitHub: ronaldoussoren).


Eventloops on secondary threads should work fine, but I don't know if CBCentralManager works on a secondary thread.

I don't know when I'll add dispach_queue_t wrappers, but those are fairly high on my list because more and more APIs use them.

ronaldoussoren commented 6 years ago

Original comment by WayneK (Bitbucket: WayneK, GitHub: WayneK).


Hi,

It would appear that to run CoreBluetooth on a secondary thread then using a dispach_queue_t is necessary.

"If you want to use a different thread to do more sophisticated things, then you need to create a queue and pass it..."

Source: https://www.invasivecode.com/weblog/core-bluetooth-for-ios-6-core-bluetooth-was/

I was wondering what level the complexity in dispach_queue_t wrappers might be?
By that I mean to understand could the wrapper be a simple API 'pass-thru' style? Such that a novice to this could 'have a go', or, do they need to be more complex (e.g. stateful and Py/ObjC thread aware) and require more pervasive changes to PyObjC, so better left to someone more experienced?

Thanks Wayne

ronaldoussoren commented 6 years ago

Original comment by WayneK (Bitbucket: WayneK, GitHub: WayneK).


I've tried creating a dispatch queue using the 'ctypes' module and then passing it to PyObjC.

I have a standalone example here: https://gist.github.com/WayneKeenan/bcf018413547c3abe7b6de3716b87bfa

Unfortunately it seg faults, am I being somewhat hopeful in trying to hack it together like this?
It could just be a ctype usage issue of my own doing that is stopping this from working.

Thanks Wayne

ronaldoussoren commented 6 years ago

Original comment by WayneK (Bitbucket: WayneK, GitHub: WayneK).


Is my attempt at trying to pass the ctypes dispatch_queue_t opaque pointer failing because it's not of a type supported by the PyObjC parameter proxying mechanism ?

ronaldoussoren commented 6 years ago

Original comment by WayneK (Bitbucket: WayneK, GitHub: WayneK).


yes, it was the proxying, I needed to wrap the parameter using objc.objc_object()

ronaldoussoren commented 6 years ago

Original comment by WayneK (Bitbucket: WayneK, GitHub: WayneK).


I've updated the gist with the working code.

ronaldoussoren commented 6 years ago

Original comment by Ronald Oussoren (Bitbucket: ronaldoussoren, GitHub: ronaldoussoren).


FWIW, I've started work on libdispatch bindings.

Those will work on macOS 10.10 or later, because the libdispatch types are Objective-C classes starting at that release and that makes wrapping a lot easier.

The initial commit is in the branch add-libdispatch-bindings, and is incomplete. Once I'm happy with those bindings I'll update the metadata for other APIs using libdispatch types and everything should then work out of the box.

ronaldoussoren commented 6 years ago

Original comment by WayneK (Bitbucket: WayneK, GitHub: WayneK).


fantastic, great news. I will keep an eye on it and test when/where I can to give feedback.
Is there an dedicated task/issue I can 'watch' to get notifications? (assuming this one isn't the right place)

ronaldoussoren commented 6 years ago

Original comment by Ronald Oussoren (Bitbucket: ronaldoussoren, GitHub: ronaldoussoren).


Not really. I expect to finish the work this weak, and include the new bindings in PyObjC 4.1 (which I want to release before the end of the year)