[HN Gopher] Metaprogramming custom control structures in C (2012)
___________________________________________________________________
Metaprogramming custom control structures in C (2012)
Author : ingve
Score : 46 points
Date : 2021-07-09 09:08 UTC (1 days ago)
(HTM) web link (www.chiark.greenend.org.uk)
(TXT) w3m dump (www.chiark.greenend.org.uk)
| adamnemecek wrote:
| So much time has been spent on making C something that it's not.
| Sure. It's interesting, but then some people start thinking that
| this is the way you should be writing C.
| MaxBarraclough wrote:
| > So much time has been spent on making C something that it's
| not.
|
| GObject is a great example of this. It's a library for doing
| OOP with C, rather than switching to C++. It's clunky enough
| that they ended up making a whole new language which compiles
| to C/GObject, called _Vala_.
|
| Vala rarely gets attention these days, but it's worth reading
| about.
| https://en.wikipedia.org/wiki/Vala_(programming_language)
| pjmlp wrote:
| Here is another example, COM or as it originally started OLE.
|
| Yes, basically it is C OO ABI, however only masochists would
| use it as such.
|
| Everyone else just reaches for VB 6, C++ (MFC, ATL, WRL, WIL,
| C++/CX, C++/WinRT, yeah I know, so is WinDev....), .NET,
| Delphi, C++ Builder, ...
| MaxBarraclough wrote:
| I have to admit ignorance on exactly what COM does. Doesn't
| Direct3D (all versions including the latest) use COM
| despite being essentially a C++-only API?
| pjmlp wrote:
| Yes, they are COM based APIs.
|
| All modern Windows APIs use COM to great extent, anyone
| that uses pure Win32 APIs is basically frozen in Windows
| XP view of the world.
|
| Mini-history lesson, initially there was DDE, which
| allowed for basic IPC on Windows 3.x, then came OLE 1.0,
| both required endless amount of C boiler plate.
|
| Then someone realized that from all concepts, there was a
| set of central ideas and Windows OO ABI was born, which
| basically maps to structure with function pointers,
| naturally with the same layout as Windows C++ compilers
| organize their vtables when using single inheritance.
|
| So then we had OLE 2.0, COM, OCX, ActiveX, mini-COM,
| which are basically all the same, IUnknown interface with
| three methods QueryInterface(), AddRef() and Release(),
| everything else builds on top of that.
|
| WinRT/UWP is COM updated with some of the ideas that were
| actually behind .NET birth, so alongside IUnknown there
| is IInspectable.
|
| So on Windows any language that understands COM ABI (not
| only C++) can make use of an OS wide OO ABI.
|
| Then there are lots of things one can do with it,
| regarding in which memory space those components run, how
| many threads they use, security,...
|
| Going back to the initial question, it is designed to be
| called from C as well, but almost no one does it.
| danlugo92 wrote:
| 9 out of 10 times good old `doSomethingWith(foo: Foo)` style C
| is better than c++/whatever `foo.doSomething()`.
| BenFrantzDale wrote:
| Contemporary C++ encourages this too. There's a place for
| member functions--even convenience ones--but algorithms
| operate on data structures; they needn't be part of the data
| structures.
| pjmlp wrote:
| Since STL was introduced actually, even if functors were a
| bit painful to write, however if you look at codebases like
| Android, there is some catch up to do with modern times.
| veltas wrote:
| I played with this kind of C, and it seems to be attractive to
| HN. Applying C's own (albeit limited) type-safety and
| encapsulation features where I can, but not going too exotic or
| trying too hard to be another language, seems to be the right
| compromise for me.
| atom3 wrote:
| When I found out about this, I wrote some macros to replicate
| some of the semantic of ISPC [1] in C++ as a fun experiment [2].
|
| Of course it has no practical value but it was really cool to see
| it was possible to do so.
|
| [1] https://ispc.github.io/
|
| [2] https://github.com/aTom3333/ispc-in-cpp-poc
| glouwbug wrote:
| I once back ported the core of the C++ STL to C to introduce
| templated containers to C with some macro magic. I learned in the
| end that I'm better off using C++
| jstimpfle wrote:
| Maybe you're just better off not porting the STL :P
| glouwbug wrote:
| It was a learning experience. And you're right, the real
| learning experience was to not port the STL
| kleton wrote:
| klib? https://github.com/attractivechaos/klib
| glouwbug wrote:
| CTL. https://github.com/glouw/ctl
|
| It's functionally blackbox compatible with the STL for the
| major containers. Unless you're writing heap spaced firmware
| where C++ with an STL isn't available I recommend you just
| use modern day C++.
|
| Unless, of course, you want blazing fast compile times!
| ludamad wrote:
| I'm curious about how much easier it is to optimize
| compiler time for macros rather than templates here. In
| theory they wouldn't be all that different, but in practice
| it doesn't seem so
| glouwbug wrote:
| CTL just copy pastes a bunch of code via an include for
| each new type. The following two tidbits are basically
| the same thing:
|
| CTL #define P #define T int
| #include <vec.h>
|
| STL #include <vector> template
| class std::vector<int>;
|
| C++ with its STL is just dramatically slower at compiling
| it all. C loves to chew through its basic syntax and O(1)
| lookup since every symbol is essentially unique (take
| that C++ and your function overloading!)
| eps wrote:
| Intrusive containers are a way more natural fit for a C
| codebase. They are also a superior choice for C++ code. The
| one and only plus of STL containers is that they come
| standard.
| wudangmonk wrote:
| If you want to use metaprogramming in C you are better off doing
| the parsing/tokenizing yourself and creating your own macros than
| trying to use the C preprocessor, its a lot less work.
| bruce343434 wrote:
| So basically create your own language + compiler that compiles
| to C?
| auxym wrote:
| Or use Nim, which compiles to C :)
| bruce343434 wrote:
| To each their own :)
| wudangmonk wrote:
| Yes, its less work
| ludocode wrote:
| But then your code can't be used by anyone without your
| preprocessor. There is a lot of value in plain C
| metaprogramming because it can be compiled with an ordinary C
| compiler.
|
| You can, however, use a script to generate some of the
| preprocessor boilerplate while still having the templates
| configurable and instantiable with an ordinary C compiler. This
| is how my metaprogramming library Pottery works:
|
| https://github.com/ludocode/pottery
|
| It uses #include for templates rather than code block macros,
| something the article doesn't really go into. It's more
| powerful this way and the templates are far more readable;
| aside from the generated metaprogramming boilerplate, the
| templated code looks like (and preprocesses to) ordinary C.
| dmateos wrote:
| Your scientists were so preoccupied with whether or not they
| could, they didn't stop to think if they should.
| veltas wrote:
| If you introduce stuff like this into C it's major code smell. If
| I see a 'cool macro to do a custom loop' in code I immediately
| have to go look up what it does, and if it's as complicated as
| this I'm going to want to read it all to make sure it's actually
| right, I'll probably rediscover all the caveats he has at the end
| of the article, and I'll wonder what the original programmer was
| smoking.
| pwdisswordfish8 wrote:
| Indeed, better to just use C++.
| veltas wrote:
| So I can implement code smell without ever leaving the
| comfort of C++? I've seen much scarier footguns in C++ than
| I've ever seen done in the C preprocessor.
| jacoblambda wrote:
| I think what OP did was taking it a bit far but xacros
| definitely have their place in C. Most notably they are
| extremely useful for instantiating hardware interfaces that
| often come with large amounts of boilerplate.
|
| I've also found use in them in combination with `_Generic` for
| implementing generic containers/data structures. Of course I
| don't use these all the time by any means but if I'm going to
| be using a complex data structure I might as well just use an
| xacro to do a glorified copy-paste for the structs and
| accessors. It's all type safe, doesn't make the code any less
| readable IMHO, and it's surprisingly very debugger friendly.
|
| The xacros used for this are all together only about 10 lines
| of code but they've saved me countless hours of work/headache
| over the years and I've never once seen them blow up in a way
| that isn't immediately diagnosable and fixable.
|
| I understand that macros are by no means to be used everywhere
| but I do find that macros/xacros provide an incredible amount
| of utility when putting together "library" or "HAL" code where
| there's a well defined interface but the internals can largely
| be hidden from the user/developer.
|
| Of course I'd generally just prefer to use C++ but when that's
| not an option or would add undue friction, I find macros/xacros
| to be a useful tool for a developer.
| veltas wrote:
| I don't see any mention of xacros in the article.
| toomanyducks wrote:
| A while back I saw someone implement pattrn matching over
| Rust/Haskell-like algebraic data types with macros in C99. Think
| it was called something like Datatype99
| Zababa wrote:
| Here's a link: https://github.com/Hirrolot/datatype99
___________________________________________________________________
(page generated 2021-07-10 23:01 UTC)