[HN Gopher] Native Mac APIs for Go ___________________________________________________________________ Native Mac APIs for Go Author : maydemir Score : 307 points Date : 2021-02-04 16:33 UTC (6 hours ago) (HTM) web link (github.com) (TXT) w3m dump (github.com) | Klonoar wrote: | This is seriously cool. I feel slightly validated that I've also | been wrapping these by hand, since it's kind of quirky to try and | auto-generate these while keeping the same usability and such as | their original incarnations. | | For those interested in a Rust variant, I've been hacking on one | for awhile: https://github.com/ryanmcgrath/cacao | | I wouldn't say it's yet ready for production use, but so far it's | working pretty well for me. Been dogfooding it by building an app | I've wanted for a bit - a proper magic-wormhole macOS app. | | One of the things I've really wanted to keep to is the delegate | pattern, since I think it actually works really well for Rust's | model. A fun example I finished yesterday is ListView cell reuse: | | https://twitter.com/ryanmcgrath/status/1357097991081844737/p... | | Ultimately I view this as one of the last pieces needed for a | cross-platform Rust UI framework to actually work. | [deleted] | dvt wrote: | Great work, OP. | | However, I think it's problematic that modern languages (Go, | Rust) don't provide these kinds of bindings out of the box. I | honestly think it's probably starting to be "in-scope" for | standard libraries. I'm working on a side-project now which needs | a desktop app, and I'm actually using Fyne[1] because it makes | cross-platform development semi-easy (even though it doesn't look | native, nor particularly great). The alternative is using either | Electron or using something like this for OSX, using something | else for Windows, and using something else for Linux. | | Window/widget/notification/taskbar APIs are stable for all major | operating systems, and it seems like we keep reinventing the | wheel here. | | [1] https://fyne.io/ | jfb wrote: | We used a lot of PyObjC BITD at Apple to explore frameworks that | we couldn't get documentation for. That was simultaneously | awesome and so so so broken, from an organizational perspective. | revskill wrote: | So we could use Go to develop iPhone apps ? | gspq wrote: | You can use Gomobile for that. | tectonic wrote: | Most of Jeff Lindsay's stuff is worth checking out. He also | started dokku and coined the term webhook. | 52-6F-62 wrote: | We use Dokku on the regular for a number of small services at | work. It was a little strange being new to it, but it's been | great. Kudos to him. | asaddhamani wrote: | I know it's kind of going against the idea of Dokku, but can | it be made to scale across servers? I love the simplicity of | Heroku but the cost can be a barrier for some use cases. But | k8s is too complicated. Anything like Dokku that scales | horizontally? | cweagans wrote: | The scheduler in Dokku is pluggable. You can use Kubernetes | or Nomad: http://dokku.viewdocs.io/dokku/advanced- | usage/schedulers/alt... | phamilton wrote: | If I were avoiding heroku because of cost and had a need to | scale horizontally, I'd use Fargate with spot instances. | | Manage it with CDK or terraform. As long as you have enough | containers running, spot ends up being a non issue. | qbasic_forever wrote: | It's even simpler now, lambda supports running docker | images as of a couple months ago: | https://aws.amazon.com/blogs/aws/new-for-aws-lambda- | containe... | jamesmishra wrote: | I also recommend this path, but I found it really hard to | write all of the required Terraform for the VPC, security | groups, load balancers, and Fargate configuration. | | So I put together an open-source Terraform super-module | to automatically set all of that up in a few lines of | code. | | https://provose.com/ | ipmb wrote: | shameless plug... you might be interested in | https://apppack.io. I built it for very similar reasons. | qbasic_forever wrote: | Look at a hosted knative solution, like Google Cloud run or | one of many others: https://knative.dev/docs/knative- | offerings/ You don't have to know or care about anything | Kubernetes with it, but you get ease of just throwing | containers at something and having it run them for web- | scenarios. They scale up and down to zero so you aren't | paying a cost when nothing is happening. And when/if you | need it, you have the full power of a kubernetes cluster at | your fingertips too. | | AWS lambda can run plain old docker containers now too. | Check out something like the serverless framework to make | it easy to define a bunch of web services or APIs and | deploy to lambda, knative, etc. | joshmanders wrote: | If you're looking for a cost-effective alternative to | Heroku, might I suggest signing up for my product | https://primcloud.com. We're pushing towards public | availability by end of February early March at the absolute | latest. | | I'm a former lover of Heroku and maintainer of Dokku. | jtsiskin wrote: | This is the same concern I had. I settled on Caprover | (https://caprover.com/), seems to exactly fit the bill. | turtlebits wrote: | flynn.io was the product I used found when I wanted a | little better scalability than Dokku. This was a few years | ago when I tried it, so unsure of the current landscape. | asaddhamani wrote: | I had tried flynn in the past (a few years ago just as | you) but couldn't get it to work, but that was with | Meteor which has very specific deployment requirements. | I'll try out flynn when I need to scale beyond Dokku. | goliatone wrote: | For my hobby servers I have tried dokku, Flynn and | countless other similar solutions. Settled with | caprover[1] and very happy with it | | [1] https://caprover.com | dimitrios1 wrote: | also wrote registrator which helped pioneer the technique of | service discovery we see in so many cloud tools and platforms | today. | monadic3 wrote: | Old is new again, apparently. :) | progrium wrote: | also helped design docker (the good parts) and a bunch of | other stuff | lunixbochs wrote: | I don't see an @autoreleasepool anywhere in the source, which I | believe means calling some AppKit APIs from Go-managed threads | will silently leak memory (due to memory allocated internally by | the APIs that will never get released). | | In my own projects, I had to wrap calls from foreign threads into | AppKit APIs with an @autoreleasepool {} block or my app would | leak memory. [1] | | [1] | https://developer.apple.com/library/archive/documentation/Co... | progrium wrote: | I thought I wrapped NSAutoreleasePool but maybe I just used it | directly dynamically. If something is not wrapped in the source | that doesn't mean you can't use it. | objc.Get("NSAutoreleasePool").Alloc().Init() | | Unfortunately I can afford some leaks at the moment, so if | that's critical to anybody else and I'm doing something wrong | just submit a PR | lunixbochs wrote: | Ah, I don't just mean the class, I mean you need to have an | autoreleasepool block active before calling into AppKit | otherwise you can leak memory on every call. It doesn't look | like you're using pools yet, or documenting that users of | your library should use them. | | See here: https://developer.apple.com/library/archive/documen | tation/Co... | | > Cocoa always expects code to be executed within an | autorelease pool block, otherwise autoreleased objects do not | get released and your application leaks memory | progrium wrote: | I guess I will look into this as that really sounds like | syntactic sugar for something more basic. Like using the | class. | | I have a hard time keeping up with their changes but you | might be right: https://developer.apple.com/documentation/f | oundation/nsautor... | | Oddly it says you cannot use them directly, but later | implies maybe they are just less efficient. It would be | nice if somebody made an issue for this. | lunixbochs wrote: | This answer says the block is more efficient than | manually managing NSAutoreleasePool objects: | https://stackoverflow.com/a/12448176 | | This answer looks like a better overview of what the | runtime is doing: https://stackoverflow.com/a/21010442 | | The @autoreleasepool block seems equivalent to this: | ctx = _objc_autoreleasePoolPush() defer | _objc_autoreleasePoolPop(ctx) | | You could maybe provide sugar for it like this: | https://play.golang.org/p/dljXN3BdEGr | progrium wrote: | Awesome, can you throw into an issue? | lunixbochs wrote: | Done https://github.com/progrium/macdriver/issues/12 | progrium wrote: | wow, thanks! | pjscott wrote: | The page you linked is not actually ambiguous, though | perhaps a bit tricky to read. It says: | | 1. If you're compiling Objective C in ARC mode, you can't | use NSAutoreleasePool directly, and must instead use | @autoreleasepool. | | 2. In manual reference counting mode you can use either | NSAutoreleasePool or @autoreleasepool, but the latter has | lower overhead. (This may matter if e.g. you're draining | the autorelease pool on every iteration of a loop to | reduce memory spikes.) | | Under the hood -- at least on the version I disassembled | -- NSAutoreleasePool's -init and -release methods wrap | the CoreFoundation CFAutoreleasePoolPush and | CFAutoreleasePoolPop functions, which in turn call the | runtime's objc_autoreleasePoolPush and | objc_autoreleasePoolPop functions, which are the things | that @autoreleasepool will cause the compiler to emit | directly. | JacobCarlborg wrote: | D has native support for calling Objective-C. No need to | integrate with the Objective-C runtime directly. Everything is | written using familiar D syntax. No extra overhead compared to | Objective-C. The generated D code is the same as the Objective-C | compiler would generate. | | https://dlang.org/spec/objc_interface.html | hu3 wrote: | Although it's a bit out of the etiquete to post tangents like | this, I find it really cool that D has such native support and | will be reading more about it because you shared. So thanks. | w0mbat wrote: | I am freaked out by the line, "Retain and Release methods for | working with Objective-C garbage collection". | | Do they mean the abandoned GC system Apple tried, or the obsolete | manual pool-based system Apple used to use? | | Either way, I want ARC instead. | progrium wrote: | sorry I meant memory management not garbage collection. again | they're just convenience methods wrapping those exact methods | on NSObject | hctaw wrote: | Last I tried to bind to ObjC APIs through C you needed to use | NSAutoReleasePool at some point, and to interact with the GC as | the APIs expect. | | There was no option to use anything else. Has that changed? | w0mbat wrote: | ARC is built on top of the retain/release pool system, but it | automates everything from the programmer's point of view so | you almost never have to explicitly interact with it. | hctaw wrote: | This works across FFI? How? | JonathonW wrote: | Retain/Release methods would be for manual reference counting, | as is traditional in Obj-C/Cocoa. | | ARC is a compiler trick in the clang objective-c and swift | compilers-- essentially injecting the appropriate | retain/release calls for you. You won't get that for free in Go | (because, again, it's a compiler feature-- compiled ObjC/Swift | code is still calling retain/release just like you would | manually), but I'd expect some integration with Go's memory | management system so you're not having to make those calls | manually. (It looks like that is not here in this particular | release, though-- they have retain/release calls in some of | their examples.) | | Objective-C garbage collection is not a thing any more, and | hasn't been for quite some time. Deprecated back in macOS 10.8, | and outright removed in more recent versions of the runtime (it | was never available on iOS, and was taken out sometime around | macOS 10.12 on desktop). | progrium wrote: | age old problem, i should definitely warn people about memory | management implications. what would you put in the readme for | this? | lunixbochs wrote: | Do the BridgeSupport files annotate whether you own | returned objects and need to release them? Sprinkling in | runtime.SetFinalizer calls based on ownership would be | slightly nicer than exposing release/retain. | gspq wrote: | Looks cool. What about Swift support? | casey wrote: | This is great, I've done a few one-off go wrappers of objective C | libraries [1][2] for an OSX menuapp framework I built [3]. | | This seems like a much more general and useful solution, excited | to switch some things over to it! | | [1] https://github.com/caseymrm/go-pmset | | [2] https://github.com/caseymrm/go-smc | | [3] https://github.com/caseymrm/menuet | coetry wrote: | This looks really cool! Is there any overhead with using these | bindings as opposed to using Swift and calling the APIs directly? | axaxs wrote: | > Is there any overhead with using these bindings | | Not the author, but yes. Go calling C is expensive, and that's | precisely how this works. Whether or not that matters for your | use case is another topic. | lsllc wrote: | There's a bit of a write-up here: | | https://www.cockroachlabs.com/blog/the-cost-and- | complexity-o... | | In their benchmark, calling a `func() {}` in Go vs a `void | foo() {}` in C (via CGo) is almost 100x faster. | $ go test -bench . -gcflags '-l' # disable inlining for | fairness BenchmarkCGO-8 10000000 171 | ns/op BenchmarkGo-8 2000000000 1.83 ns/op | | EDIT: And then you still have the extra overhead when using | `C.CString` and `C.GoBytes` if you're passing those sorts of | arguments to C. | _ph_ wrote: | But if the called function takes more than 200ns to | execute, the overhead is less than 50%. Which probably is | true for most relevant functions in an API | _ph_ wrote: | Go calling C is expensive compared to the normal function | call overhead, but if the called function does significant | work, should not introduce too much overhead. | MaxBarraclough wrote: | > Go calling C is expensive | | Is this true even if only primitives are passed and returned? | If so, why? For comparison, Java is fast at that these days, | if I understand correctly. | | (Interesting related reading regarding Java: | https://web.archive.org/web/20160304055443/http://nerds- | cent... ) | progrium wrote: | This is a good question that should be added in the readme. | Would love an issue for it to also collect data ___________________________________________________________________ (page generated 2021-02-04 23:00 UTC)