madsmtm / objc2

Bindings to Apple's frameworks in Rust
https://docs.rs/objc2/
MIT License
349 stars 40 forks source link

Delegate/Protocol methods not getting called #472

Open hydrobeam opened 1 year ago

hydrobeam commented 1 year ago

Hi! I've been messing around trying to get ScreenCaptureKit to work and capture a display. I've gotten to the point where the capture succesfully starts, but the methods that are supposed to be handling the output aren't being called externally (but they do trigger when I call them manually).

the two methods that are supposed to be triggered are from:

Here's a link to my demo repo for testing if you'd like to look at the code: https://github.com/hydrobeam/osx_windows_demo/tree/65d11893b7bc815f0d8adeafc41dd30e10a07b4b

I'm not sure if I've defined the external protocols properly or if it's just a case of me not working with ScreenCaptureKit properly. I've checked quite a bit to make sure I don't have basic typos and that the methods I've defined actually correspond to the ones expected by the API, but there's still a chance I might've missed something since it seems to just fail silently.

If you have any suggestions or tips on how to debug this I'd appreciate them!

madsmtm commented 1 year ago

Thanks for the detailed issue and reproducer.

I am in the process of acquiring a new macbook, so I suspect it will take some time before I will be able to fully diagnose your issue myself.

I do have a suspicion that it's because the protocol is not registered by the runtime, which means that objc2 can't (for now at least) register the class to conform to it, yet ScreenCaptureKit requires the conformance on the runtime level.

Could I get you to give me the output of runtime::Protocol::get("SCStreamDelegate") and runtime::Protocol::get("SCStreamOutput")?

If those return None, then that's likely the problem, and you will need to link in an Objective-C library with the following code (untested, maybe you'll have to make these symbols used somehow to make the C compiler not strip the information completely, I can't quite remember how to do that though):

#include <objc/runtime.h>
#include <ScreenCaptureKit/ScreenCaptureKit.h>

// Define two globals that reference each protocol, to make sure they are
// initialized in the Objective-C runtime.
Protocol* SCStreamOutput_protocol_hack = @protocol(SCStreamOutput);
Protocol* SCStreamDelegate_protocol_hack = @protocol(SCStreamDelegate);
madsmtm commented 1 year ago

https://github.com/madsmtm/objc2/issues/417 also has roughly the same workaround (again, in case that is indeed the issue)

madsmtm commented 4 months ago

I've recently added objc2-screen-capture-kit (full version not yet released, but you can tell cargo to fetch it from this repo). Please update your example code to use that, then we're at least sure that the problem isn't with your msg_send!s.

Another issue might be that the application needs to be running, instead of just sleeping on the main thread? Try setting up an application delegate and calling everything inside applicationDidFinishLaunching:, you can find a full example of that here.