You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm trying to hook into Apple's GCD method dispatch_async to schedule callbacks on the main thread. I've gotten pretty far but the final call never returns.
The obj-c code I'm trying to replace is:
dispatch_async(dispatch_get_main_queue(), ^{
// some code
});
I discovered that dispatch_get_main_queue is actually a macro and returns the address of _dispatch_main_q.
The following is where I'm up to. It feels like I'm missing just one final piece:
funcdispatchTest() {
libSystem, err:=purego.Dlopen("libSystem.dylib", purego.RTLD_NOW|purego.RTLD_GLOBAL)
iferr!=nil {
panic(err)
}
dispatchMainQueue, err:=purego.Dlsym(libSystem, "_dispatch_main_q")
iferr!=nil {
panic(err)
}
vardispatch_asyncfunc(uintptr, uintptr)
goFunc:=func() {
fmt.Println("Hello from the main thread")
}
callback:=purego.NewCallback(goFunc)
purego.RegisterLibFunc(&dispatch_async, libSystem, "dispatch_async")
dispatch_async(dispatchMainQueue, callback)
println("i never get here")
}
funcmain() {
// Since the error wasn't checked before check it before calling any code.NSApp:=NewNSSharedApplication()
gofunc() {
time.Sleep(1*time.Second)
dispatchTest()
}()
NSApp.Run()
}
The NSApp code is just the same as from last ticket so left out to simplify the example.
Nothing is crashing or suggesting anything bad is happening. Am I using NewCallback correctly? My guess is that it's to do with C vs Obj-C calling conventions...
From my research I've discovered that blocks are not the same thing as a normal C function pointer despite the fact that it's header definition would like you to believe so. My suspicions were raised by this gist. See Block_private.h which shows that its implementation is an ObjC object. Now there are no public nor private methods for creating a Block struct that I can find. So I don't think it's a good idea to attempt to create one of these. Here's an article about its implementation. I'd recommend choosing a different approach. One perhaps where you intercept the main run loop and use go channels to pass the Go callback and run it on the main thread. I think ebitengine does something similar using glfw
Activity
TotallyGamerJet commentedon Apr 12, 2023
So it does crash on my system (M1 Max, 13.3.1).
From my research I've discovered that blocks are not the same thing as a normal C function pointer despite the fact that it's header definition would like you to believe so. My suspicions were raised by this gist. See Block_private.h which shows that its implementation is an ObjC object. Now there are no public nor private methods for creating a Block struct that I can find. So I don't think it's a good idea to attempt to create one of these. Here's an article about its implementation. I'd recommend choosing a different approach. One perhaps where you intercept the main run loop and use go channels to pass the Go callback and run it on the main thread. I think ebitengine does something similar using glfw
leaanthony commentedon Apr 12, 2023
Thanks for taking the time to respond to this 🙏Blocks are NASTY! I'll look at how to get the main loop running in Go and pump Cocoa's event loop 👍
TotallyGamerJet commentedon Aug 24, 2023
@leaanthony Hey! So I came across DarwinKit and it appears they support blocks. Looking at the code it appears to also be possible to do with purego. I hope this helps! https://github.com/progrium/macdriver/blob/main/objc/block.go
leaanthony commentedon Aug 24, 2023
Thanks for replying! How would it be possible in purego?
TotallyGamerJet commentedon Aug 25, 2023
This gist is basically replacing each call to C with one using purego
leaanthony commentedon Aug 25, 2023
The linked source code appears to use CGO? Maybe I'm missing something?
TotallyGamerJet commentedon Aug 26, 2023
Yes replace the calls to Cgo with purego calls to those same functions
hajimehoshi commentedon May 4, 2024
I'd like to use dispatch_data_create, and this requries a block. In the current situation, we should create a block by ourselves reffering https://github.com/progrium/macdriver/blob/main/objc/block.go, right?
TotallyGamerJet commentedon May 4, 2024
Yes refer to that code on how to implement a dispatch block.
leaanthony commentedon May 5, 2024
Amazing! If you get a basic example working, please share! 🙏
hajimehoshi commentedon May 5, 2024
In my use case, passing 0 (NULL) to a block argument was enough, so I realized I didn't have to port that...
purego issue 129: Add ObjC Block Support
purego issue 129: Add ObjC Block Support
Add support for Objc blocks (#325)