10 ms·
Very nice code quality. C gets a hard time and this code base highlights some of the modern features C is missing by its use of perfectly clear workarounds. E.
by CraigJPerry 5y ago
Very nice code quality.
C gets a hard time and this code base highlights some of the modern features C is missing by its use of perfectly clear workarounds. E.g. The prefix “namespacing” done here works just fine, easy to understand. The go-style visibility approach is growing on me lately and it works well here.
C does deserve some of the criticism right enough, e.g. the same macros re-defined in a few places - it’d be nice if c had a better way than its version of macros although its not actually a problem here because the macros aren’t really big enough to have subtle sharp edges.
Ahh a beautifully written project, just shows that maybe C is entirely workable in the right hands.
- kungito 5y agoWorkable for what? Is this production ready? How many refactorings can this code survive? Don't get me wrong, I haven't read this code so I'm not talking about this project spcifically, but I keep getting triggered by the apologism about languages with poor or no types. Can we finally drop this myth about "bad languages are good when used by smart people"?
- visualradio 5y agoIf a project requires an open API like OpenGL, SDL, Vulkan which is documented and defined using ANSI C or C99 language constructs, then some amount of C is required regardless of the merits of the language. With high level language with large community maybe someone writes and maintains wrapper, library, or FFI binding for you but this relies on economy of scale and out-sourcing work. If a programmer doesn't understand a C API then writing a binding to a function they don't understand in order to test it is a point of friction which encourages returning to plain C. Ideally more of the "Better C" languages would retain ability to parse and compile vanilla C header files without manual binding. Zig attempts this but reduces the cognitive simplicity of the language by using structs as namespaces for holding local function definitions rather than as "plain old data".
- whateveracct 5y ago> Ideally more of the "Better C" languages would retain ability to parse and compile vanilla C header files without manual binding. I've been doing a lot of zero-copy FFI work in Haskell. It became quite mechanical to create 100% literal bindings to C libs (Pointers and all), and it's nice to use it directly in Haskell as-is. I'm hoping I can write a simple tool to do exactly what you describe.
- visualradio 5y agoFor programmers which need to consume C APIs ideally the tool is the standard compiler. Eeverything gets handled at compile time without the need for community-maintained cache of bindings. New language designers start with a C compiler which handles header files, then extend compiler to also parse NewLang files. The in-memory representation is loaded from both source types, without throwing away the C functionality. In NewLang there is some standard namespace and calling convention. @importc "stdio.h" num : I32 : 123456789 fd : c:int : c:open(c:"file.txt", c:O_RDONLY) :: c:print("file:%d number:%d\n", fd, num) But nothing more, everything else is handled by compiler.
- whateveracct 5y agoFor a "Better C" language, that would be wonderful. For my Haskell ideas, generating Haskell from headers automatically feels like the best route. Especially if it's configurable to some degree. It's common that you can better type a C API with Haskell than C ever could. Usually with techniques like IO, phantom types, GADTs, and the new linear types.
- visualradio 5y agoThe chicken-and-egg problem is where programmers don't know how the C API works well enough to provide function-specific type annotation or library-specific configuration settings, but want to try calling the API anyway because they are following a tutorial written in C or C++. In this situation if there is no "dumb" binding mode builtin to the language the programmer is likely to abandon the language and go back to writing C or C++ until they get the IO working and something displayed on screen.
- bsder 5y ago> Ahh a beautifully written project, just shows that maybe C is entirely workable in the right hands. And because it is in C, you can talk to it from Nim, Python, Rust, etc. And scripting is a very big part of RTS games.
- aydwi 5y ago> And because it is in C I'm curious, what difference does it make if it was written in, say, Rust, or C++. Wouldn't you still be able to talk to it in a similar way? What's so special about C in this context?
- steveklabnik 5y agoYou can expose a C ABI from Rust, and some folks do, but it takes some work. Some people don’t find that acceptable.
- tdhz77 5y agoTo me, If it solves the problem it’s acceptable.
- chris37879 5y agoThe thing that's always special about C, it's basically the default goto programming language for calling from higher level code, most languages that support FFI do so by being able to communicate with C apis and having tools written around C. C also lacks more complex things like classes, it's much easier to build up a complex piece of software from C building blocks bound to your language. Think of like a struct that has a set of functions that operate on it. You can map that basically directly to a class definition in most higher level languages and then wrap up the c implementation details like memory management behind the scenes so you can produce a nice clean api in your chosen language to use. This practice is fairly common in python when you're dealing with AI (I'm sure there's other examples, but this is the one that sticks out to me.) SDKs like TensorFlow are written in a lower level language (C++ I think for TF) and then FFI called from python, so you can end up with a function like initTensorFlow() and calling it is enough to bring TF online and ready to start processing other data. And you may be thinking "Well, I can do all that in rust or go or <insert prefered language here>" and of course you can, ultimately it's all just a linker and compiler deciding where to put code and data in an executable, but C is the defacto standard and more tools from more languages are going to work well with it than say, rust or go. Which, now that I think about it, is probably why Rust supports defining a c api for your code, so it's easier to call from other platforms. Rust specifically tries to play nice with being embedded in existing projects because it makes it easier to adopt rust incrementally. Just my $0.02
- camjohnson26 5y agoWhat’s the reason for serializing the full engine state for the save/load functionality? Seems like a lot of complexity.
- mcdevilkiller 5y agoI guess because RTS games are soft-realtime systems and need precise control of everything. RTS multiplayer logic is some of the most complex I've ever seen, these games are basically distributed computing frameworks.
- isaacremuant 5y agoThe last paragraph sounds so no weird to people who have worked years of their life in firmware development. Of course it's workable. It does have a lot of gotchas and seems to foment a propensity to reinvent the wheel (Although that also relates to the limited contexts in which it is used). I'd generally avoid it unless it really is the right tool, in which case, just approach it in a methodical way, like every other project.
- WFHRenaissance 5y agoCan you elaborate on the “go-style” approach, or link an article or two?
- bcrosby95 5y agoIf you look at the source code, "public" functions are capitalized, and "private" ones aren't, by convention.
- f00zz 5y agoThe nice thing about C is that it's so small that you can hold every corner, nook and cranny of the language in your head. There must be less than a dozen people in the world that can say that about C++.
- tomcam 5y agoI count Stroustrup, Walter Bright... and 10 posers
- ssssssnakes 5y agoStroustrup once ranked himself a 6 on a scale of 1 to 10 as to how well he knows C++.
- bitwize 5y agoI've been known to rank myself as a 6 out of 10 "where 10 is Stroustrup".
- seibelj 5y agoI haven’t written C professionally or hobbily in 5+ years and I can fairly quickly get accommodated in open source projects. I know that it has many valid criticisms but C is such a pleasure.
- whatshisface 5y agoQuick, I need to parse a simple string; should I use scanf, fscanf, sscanf, scanf_s, fscanf_s, or sscanf_s?
- typon 5y agoI don't understand C programmers are their seemingly utter inability to understand that C is actually not perfect and has tons of flaws, including a lot of complexity. Just because you're used to something doesn't make that thing not complex. Try teaching C to first year undergrads.
- Hypergraphe 5y agoI see a lot of salt in the comments below on the C language. Like, "how do you scan a string", "it is unteachable to junior devs", "not because you are used to it, it does not mean it is any good", etc. Well, the same old critiscisms again and again. You can do shit in any language if you don't understand what you do. For instance, Duck typing in Python or Javascript can lead to huge mistakes at runtime, code injection and unchecked values in java can lead to severe runtime crashes, etc. So yeah basically you want good code quality (knowing what you do) and good unit testing in any language. C has proved totally workable on many occasions. I guess a lot of the comments on this thread where written from a Linux Kernel :)
- alternatetwo 5y agoOr a Windows Kernel which is also (mostly) C.
- zzo38computer 5y agoWhat I think is the greatest problem of C is the confusing syntax for types. Other than that, I think C is good (and in many ways, does many things better than a lot of modern programming languages do), although there are things I would improve (some of which are already implemented in GCC), including a few additional macro functionalities (including adding to existing macros like {append} does in Free Hero Mesh, and a kind of macros which are scoped as variables similar to vardef in METAFONT, and the ability to count the number of arguments to a macro (without expanding any of the arguments), etc)