C-Macs – a pure C macOS application

dgellow | 192 points

> A little bit of this also has to do to stick it to all those Luddites on the internet who post "that's impossible" or "you're doing it wrong" to Stack Overflow questions... Requesting permissions in the JNI "oh you have to do that in Java" or other dumb stuff like that. I am completely uninterested in your opinions of what is or is not possible. This is computer science. There aren't restrictions. I can do anything I want. It's just bits. You don't own me.

From the wonderful CNLohr's rawdraw justification[0]. I always enjoy these kinds of efforts because they embody the true hacker spirit. This is Hacker News after all!

0: https://github.com/cnlohr/rawdrawandroid?tab=readme-ov-file#...

cnity | 14 days ago

This app uses objc_msgSend, which feels a lot like cheating, but if you simply want to avoid using nibs (while still using Objective-C or Swift), check out my NiblessMenu project and my "Working without a nib" blog series.

https://github.com/lapcat/NiblessMenu

https://lapcatsoftware.com/articles/working-without-a-nib-pa...

lapcat | 14 days ago

I found this repo while looking for an equivalent to Win32 hello world[0] as a learning exercise during a long flight (with my work MacBook instead of my personal Windows machines).

That's something I really like about Windows APIs — I can pick a new programming language I want to play with, as long as there is a way to interface with C I can try to port the Win32 hello world then play around.

0: https://learn.microsoft.com/en-us/windows/win32/learnwin32/y...

dgellow | 14 days ago

Very nice. In similar fashion, a few years back I set out to create Wuhoo.

Wuhoo loosely stands for W indows U sing H eaders O nly. It is an attempt to create a single-header library (in the spirit of STB) for graphics related window management, compatible with both C and C++.

It works on Windows, Linux and Mac.

https://github.com/ViNeek/wuhoo

vineek | 14 days ago

I did a straight C++ app for MacOS but 1) I used SDL2 and 2) it was a full-screen game so no Cocoa UI needed. It was kind of fun though in a retro-computing way.

(I'm a big fan of SDL now.)

JKCalhoun | 14 days ago

If you want to optimize this (and you enjoy pain), you can eliminate the dependency on objc/* headers and use compiler attributes and link sections to compile your code to the same(ish) assembly that Objective-C compiles to. I don't have a C example on hand, but here's a Rust example that's pretty easy to translate to C: https://github.com/objrs/objrs/blob/master/HOW_IT_WORKS.md

cornstalks | 14 days ago

Good example of digging with a spoon as they stated was the original goal. And it still compiles on an M1 macbook despite being a decade old code base.

magicmicah85 | 14 days ago

As someone with no experience in native application development, could someone explain to me why this is significant? I have a rough idea, but I would like to understand it properly.

9dev | 14 days ago

Uses under 1.5 MB of memory at any one time (most of it is used for drawing the window).

Unfortunately there is no screenshot and I have no access to a Mac at the moment, but if View.c is where things actually happen, that is a huge amount of memory just for a (resizeable?) window with a little filled rectangle in it. The memory usage of a trivial app like this should be measured in kilobytes.

Comparing applications written in the same language across platforms is IMHO a good gauge of their relative efficiency. From what I've seen, Win32 and Linux (Xlib) are pretty close but Mac is clearly very "think different". I'm sure the liberal use of string constants here doesn't help either.

Here's a related interesting comparison: https://zserge.com/posts/fenster/

userbinator | 13 days ago

Here's something similar by Garrett Bass:

https://github.com/garettbass/oc

...I also experimented a bit with parsing macOS system headers via clang-ast-dump and then code-generating C and Zig bindings but that didn't get far:

https://github.com/floooh/objc-ast-experiments

...with a bit of effort and maybe using libclang instead of clang-ast-dump that's definitely feasible though.

I guess a similar approach is used by the official C++ bindings for Metal:

https://developer.apple.com/metal/cpp/

...also shameless plug: the sokol headers allow to write simple macOS applications (just a Metal canvas in a window) in various non-Apple languages (currently C, C++, Zig, Rust, Odin, Nim):

https://github.com/floooh/sokol

...I'm cheating though and use ObjC under the hood to talk to Cocoa and Metal ;)

flohofwoe | 14 days ago

Draw a line through this 12+-year-old effort from Robert Widmann and his 8-year-old exercise in type-lifting Swift [1] and ask yourself: what is he doing now at Apple?

[1] https://github.com/typelift/Swiftz

w10-1 | 14 days ago

Love this, if I never have to write a wrapper around objc again I'd be in heaven.

rdrsss | 14 days ago

For an iOS attempt, I've often gone back to this wonderful StackOverflow post: https://stackoverflow.com/a/10289913

MaxLeiter | 14 days ago

Reminds me of an app I built ~20 years ago now.

We wanted a cross-platform C++ layer and native Cocoa front end. Objective C++ wasn’t a thing then, and having built a plain C shim previously I didn’t want to repeat the experience.

We built our own bridge by registering our C++ classes with the Obj-C runtime, generating selectors for all the methods so you could send messages to (carefully constructed) C++ objects using Obj-C syntax, or even subclass from C++ to Obj-C.

It was a pretty neat trick, but would’ve been difficult to port to the Obj-C 2 runtime.

eyesee | 13 days ago

It seems that the code is the result of the ObjC preprocessor. :-)

chunsj | 14 days ago

We used the same technique to port our C applications to Apple platforms, but to do so we wrote an automated tool that created a C wrapper for any cocoa API we need. It works on all current Apple platforms we have tried it on iOS,iPadOS, and Apple Silicon Macs.

Its open source:

https://felixk15.github.io/posts/c_ocoa/

quelsolaar | 13 days ago

Seeing some confusion. This is using what are effectively FFI interfaces to the Objective-C runtime. There’s really no good reason to do this in production code that isn’t a language bridge. It’s not as efficient at runtime as writing the functionally equivalent Objective-C, because the ObjC compiler statically allocates class/method data structures, and it’s not as safe, because you’re bypassing ARC.

KerrAvon | 14 days ago
[deleted]
| 14 days ago

This is basically what Go PenPoint programming was like. When you read the Go documentation it’s very clear they intended to use Objective-C or an equivalent preprocessor; I suspect they were stymied by NeXT’s acquisition or Stepstone and their own lack of support for GNU C.

eschaton | 12 days ago

This would've been a lot easier to wrap my head around when I had to work with Objective C for the first time

jbverschoor | 14 days ago

It would be nice to have something like this except for Metal. I'm unsure why Apple made Metal an Objective-C API when C + Core Foundation would suffice. One big advantage of a C API is it's easy to interop with other programming languages.

hgs3 | 14 days ago

This would seem more complete if it had a simple Makefile rather than an xcodeproj.

ks2048 | 14 days ago

You don't need a xcodeproj at all for a pure C macOS application (or do you need it 10 years ago? I see the last commit is 10 years)

slmjkdbtl | 13 days ago
[deleted]
| 13 days ago

Crazy that this has to be a thing .. Why does Objective C even exist anyways??

cossinle | 14 days ago

No license typically means copyright with all rights reserved in the U.S.

Perhaps you want to release this into the public domain (see SQLite)?

codazoda | 14 days ago

[flagged]

beardedwizard | 14 days ago