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.
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:
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]
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
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.
> Cocoa always expects code to be executed within an autorelease pool block, otherwise autoreleased objects do not get released and your application leaks memory
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.
Keep in mind that the reason the `@autorelease` syntax is faster is primarily due to ARC optimizations (which don't apply here, since you're not using ARC).
Calling the `_objc_autoreleasePoolXX` functions are still likely to be faster than the NSAutoreleasePool objects, but only because you're avoiding the Objective-C message sends.
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?
What's another layer of abstraction on top of _Kubernetes_. #yolo
I haven't actually used k8s-backed Dokku, but I imagine that it would be worth at least experimenting with if you're already committed to running stuff on k8s.
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.
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.
I'm a pretty big fan of CDK if you are willing to make cloudformation and AWS your lingua franca. I use it for most of my personal projects, but professionally bias towards terraform.
My application is actually pretty bandwidth heavy, which removes AWS and other major cloud operators from the equation.
But I’ll keep it in mind for non bandwidth intensive workloads.
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.
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.
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.
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.
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
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.
It's a little sad that after 50 years since Microsoft and Apple were started, there still is no easy way to write a natively looking cross-platform GUI app, even with a language like Golang.
Recently I looked at couple of options of writing some Golang to make a simple GUI app that would look natively on Windows/MacOS (text area, several checkboxes/buttons), and there's no much there to be honest.
Sure there is: Write a separate UI for each platform.
Seriously, this is the only option if you care not just about looks but also about feel, because no cross-platform toolkit gets things like keyboard shortcuts, scrolling inertia, menu mnemonics, etc. correct on all platforms they target. Not to mention platform accessibility features.
Surely most of the work in your app is platform-independent, right? Plumbing data into platform-specific UIs should not be a hard endeavor.
Unironically, your best option is GTK. I've found that it generates consistent looking UIs for Linux and Windows (my main build targets) without totally ruling out MacOS
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.
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.
I don’t think it’s out of line. Oftentimes comments like this do come with jabs at the language being discussed, but this one was pleasantly free of snark. It makes me more curious about D.
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.
Do you mean we should have OS-specific methods in languages' standard libraries? Or that we should add cross-platform frameworks to languages' standard libraries?
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).
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.
Manual Reference Counting (aka Manual Retain Release) is obsolete in the sense that there's no reason for most people to use it, but it is still completely supported, and Apple themselves still have huge MRC codebases, including AppKit itself. Automatic Reference Counting (ARC) uses the same underlying reference counting mechanism, it just inserts the retain/release calls for you at compile time. (There's slightly more to it than that, especially around ARC's ability to optimize, but it's not too far off.)
The author has already clarified that Objective-C "garbage collection" wasn't really what he meant, but the distinction between ARC and MRC only makes sense in the context of the ObjC compiler itself. From the "outside", esp. for compiled binaries (like the system frameworks), ObjC classes always just use reference counting.
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.
Bindings for Apple's APIs for other languages come out every once in a while. For example, PyObjC for Python, RubyCocoa and MacRuby, Apple's own old Java bindings, etc.
Usually these garner early interest, but no significant programs come out using them, and they tend to be abandoned within a few years. I don't mean to discourage the author, but I wonder if he's aware of the history and if he has thoughts on why Go may fare better.
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.
That would be a lot more difficult (unless you limited support to the subset of Swift which is shared by Objective-C). Objective-C is an extremely simple extension to C, and has a rich runtime API. So any language which can interface with C can interface with Objective-C by using the runtime interfaces.
I successfully used the other way - calling Golang functions from iOS/Swift using Gomobile. It is working now for the new M1 Apple desktop computers too.
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.