Live data from Hacker News

OS X app in plain C

github.com

71–80 of 157 posts

Re: OS X app in plain C

#71

It's amazing and sad for computing that somehow managing to use a sane language to develop software for a very commonly used platform is seen as a serious feat of accomplishment.

C was not designed to create gui's. So its a feat of accomplishment as opening a bottle with your teeth.

I had a project once that required me to build a GUI in C using Motif. It was a joy to use. I recall there was a simple concept called RowColumn. All the GUI widgets were either in a Row or in a Column. It was highly orthogonal and allowed you to build good-looking UI's that acted in a reasonable way when resized, etc.

Re: OS X app in plain C

#72
post #57

Earlier quoted context omitted.

That seems slightly pedantic. While it's true that there's no cross-platform C ABI, most platforms have a C ABI, and it's well-defined (and defined in terms of C data types) on that platform. It's sort of like saying that there's no such thing as "rules of the road", because the road makers don't specify how you're supposed to drive on them, and the rules differ by jurisdiction and sometimes you're in a wilderness wi…

> That seems slightly pedantic. While it's true that there's no cross-platform C ABI, most platforms have a C ABI, and it's well-defined (and defined in terms of C data types) on that platform. Every platform has an ABI, obviously, and yes it's generally formed in view of C. This doesn't change the fact that the phrase "The C ABI" is, in a vacuum, meaningless and that "The C ABI on Platform X" is just a convoluted, c…

But what an ABI does is specify a binding between language-level concepts and binary representations. That's why mentioning the language matters. If "Platform X's ABI" says that structs are passed on the stack, or ints are a certain size, or pointers have a certain alignment, or whatever, it (usually) means that C structures are passed on the C stack, C ints are a certain size, C pointers have a certain alignment, etc. Another language can use its own data types and even its own concept of a stack. (For instance, Go uses a C-incompatible stack.) And the reason that we care about "the C ABI" is whether the implementation of a language on platform X has data types, stack usage, etc. that matches the implementation of C on platform X.

Put another way, I'm arguing that "C" is a more useful descriptor than "platform X's", because the sentence "Rust is compatible with the C ABI" is short for "forall X, Rust on platform X is compatible with the C ABI on platform X", and means something different from "Rust is compatible with the SysV ABI" (which implies that it follows the SysV ABI on Windows and OS X, too). And since the typical way of doing that is by interfacing with a C compiler or the C library (... and you could make this exact argument about the phrase "C library", I think), it's worth mentioning C. For instance, Vala and Nim, which both compile to C, are always compatible with the C ABI. If you port them to a mainframe they remain compatible with the C ABI, but not with the native ABI.

Re: OS X app in plain C

#73
post #64
post #49

Earlier quoted context omitted.

I said you're right and I wasn't trying to disagree. I'm also a big fan of your blog and comments here (FWIW). As for whether casts add much safety, I admitted it's debatable. C++ prefers casts (e.g. on malloc) whereas C doesn't. A downside of using explicit casts is that if the type changes elsewhere in the program, the casts (spread throughout the code) can mask errors. If you write code such that casts are unneces…

I agree that unnecessary casts are undesirable, but that seems like a completely irrelevant point here, seeing as how the casts are not optional. C++ doesn't prefer casts, it requires them in places where C doesn't. Casting the return value from malloc isn't optional in C++ (unless you're assigning to a void *, anyway).

I was referring to this part of your original post:

> It's also easy to make mistakes because of type mismatches. For example, if you pass `42` to a CGFloat parameter, this works fine when you cast msgSend to the right type, but will fail amusingly if you rely on varargs to make it through.

All of your other claims are completely valid. This one, I'd say, is partially valid.

No need to pick nits with my usage of the word "prefers."

Re: OS X app in plain C

#75
My interest in this comes from wanting to build Objective-C based OSX-UIs using scripting languages that are only embeddable in C, like Lua. When (if?) that day comes, I'll be like a kid in a candy store all over again.

Re: OS X app in plain C

#76
post #73
post #64

Earlier quoted context omitted.

I agree that unnecessary casts are undesirable, but that seems like a completely irrelevant point here, seeing as how the casts are not optional. C++ doesn't prefer casts, it requires them in places where C doesn't. Casting the return value from malloc isn't optional in C++ (unless you're assigning to a void *, anyway).

I was referring to this part of your original post: > It's also easy to make mistakes because of type mismatches. For example, if you pass `42` to a CGFloat parameter, this works fine when you cast msgSend to the right type, but will fail amusingly if you rely on varargs to make it through. All of your other claims are completely valid. This one, I'd say, is partially valid. No need to pick nits with my usage of the…

I don't understand what's debatable about that. Maybe an example would help?

    objc_msgSend(window, sel_registerName("setAlphaValue:"), 1);
Versus:

    ((void (*)(id, SEL, CGFloat))objc_msgSend)(window, sel_registerName("setAlphaValue:"), 1);
The former will set a garbage alpha value, the latter works. More generally, the former requires much more care and attention to get the types right, whereas the latter just requires that the cast match the method declaration.

Re: OS X app in plain C

#77

Don't do this at home. It looks so ugly because it's dangerous and vice-versa. If you really want to write (and read) code like this: id titleString = ((id ( )(id, SEL, const char ))objc_msgSend)((id)objc_getClass("NSString"), sel_registerName("stringWithUTF8String:"), "sup from C"); ((void (*)(id, SEL, id))objc_msgSend)(window, sel_registerName("setTitle:"), titleString); instead of this [window setTitle:@"sup"]; th…

Seriously, I don't know who's downvoting you. This needs a huge "for academic purposes only disclaimer". Higher level abstractions exist for a reason.

I think it's obvious that this is an academic exercise (or "just because I can" sort of thing), which makes the GP's comment quite unnecessary.

Re: OS X app in plain C

#78

Earlier quoted context omitted.

> The ability to use a high-level, dynamic language (ObjC), C, and even inline assembly in a single source file is unique to Objective-C (at least among the "mainstream" languages), and something I think is often under-appreciated. You can even use C++, too, which is awesome. Putting Objective-C objects in C++ structs "just works" thanks to ARC. One thing most people don't know is that Objective-C was originally impl…

Objective-C was a modification of the GCC developed by NeXT. NeXT didn't publicly release their patches and the FSF/GNU threatened legal action. NeXT released their sources and the GCC now supports Obj-C. Source: https://en.wikipedia.org/wiki/GNU_General_Public_License#Leg...

> Objective-C was a modification of the GCC developed by NeXT.

No.

Objective-C was developed in the early '80s (as a C pre-processor, as the Grandparent post said) by Brad Cox, and commercialized by himself and Tom Love via a company they created together called Stepstone. Cox wrote a book about their product, Object Oriented Programming: An Evolutionary Approach, in 1986. I own a copy. It's pretty good!

Some time later, NeXT decided to build their user-space APIs around Objective-C, and bought the rights to Objective-C from Stepstone outright. It was at that point that they started modifying GCC to directly compile Objective-C rather than pre-process it into C.

Re: OS X app in plain C

#79

Earlier quoted context omitted.

This is a very particular crowd, largely into web software and ecosystems for rapid growth of SaaS. I wouldn't extrapolate this crowd into software languages in general. You should always use the best tool for the job. Many people write quite excellent software in C/C++ every day. Just as many people use chainsaws, drive cars, fire guns and take pills every day. These are all productive activities with low floors and…

agree. If this was an enterprise/cio/it/gov discussion web site then all the conversations would be java and .net vs c++ if this was a scientific computing website then python, c/c++ and fortran and would be mentioned etc. if this was a hardware/firmware website it would be c vs (whatever black magic is used by hardware wizards).

VHDL vs Verilog flame wars everywhere. Also, discussions on people's favorite idiosyncratic, vendor-specific dialect of C for embedded devices.

Re: OS X app in plain C

#80
post #76
post #73

Earlier quoted context omitted.

I was referring to this part of your original post: > It's also easy to make mistakes because of type mismatches. For example, if you pass `42` to a CGFloat parameter, this works fine when you cast msgSend to the right type, but will fail amusingly if you rely on varargs to make it through. All of your other claims are completely valid. This one, I'd say, is partially valid. No need to pick nits with my usage of the…

I don't understand what's debatable about that. Maybe an example would help? objc_msgSend(window, sel_registerName("setAlphaValue:"), 1); Versus: ((void (*)(id, SEL, CGFloat))objc_msgSend)(window, sel_registerName("setAlphaValue:"), 1); The former will set a garbage alpha value, the latter works. More generally, the former requires much more care and attention to get the types right, whereas the latter just requires…

    ((void (*)(id, SEL, double))objc_msgSend)(window, sel_registerName("setAlphaValue:"), 1);
If the method signature changes (unlikely for a system header, but possible if you're calling into your own code) then you're hosed. Or you could just mess up and copy/paste the wrong signature, or forget to change it.

Basically, it's pretty error-prone no matter what you do. Using Objective-C directly is much safer (and luckily you usually can, since ObjC is pretty much a drop-in replacement for C).

Post reply on HN