Why the use of C++ features in the handmade source

I'll preface this by saying that I may be missing something completely so please correct me if I'm missing something.

Basically by using a mix of C/C++ we're creating a monster of a codebase that'll be tough to port later (or now in my case).

Is there a reason why we're using C++ struct definitions in the handmade source instead of just straight up C structs?

In particular I'm looking at the struct definitions in handmade.h

(example)
1
2
3
4
5
6
7
8
struct game_offscreen_buffer
{
    void *Memory;
    int Width;
    int Height;
    int Pitch;
    int BytesPerPixel;
};


For a C compiler, that struct has to be referenced as `struct game_offscreen_buffer` but the handmade source just uses it like `game_offscreen_buffer` as one would in C++.

Sure one can get around this by compiling with a C++ compiler but not every platform has (good) C++ compatibility (ie Swift).

Could make this immensely less painful just by typedef'ing the thing:
1
2
3
4
5
6
7
8
typdef struct game_offscreen_buffer
{
    void *Memory;
    int Width;
    int Height;
    int Pitch;
    int BytesPerPixel;
} game_offscreen_buffer;


Also using booleans directly which is cool in C++ but takes importing stdbool.h in C.

With those changes the entire handmade codebase becomes straight C (rather than this weird mashup of C/C++). It's not like we're using any actual C++ features anyways (ie classes, etc).

I know these are nitpicks but a few changes here and there and it will make the code much more portable and makes putting together a platform layer easier...

Edited by Karl Kirch on
Someone with more C/C++ knowledge than me will probably give you a more in depth explanation, but Casey has previously mentioned that he is writing C style C++ and he will be using more C++ features eventually, so be warned that you might run into some problems if you are working on a C++ incompatible way.
Specifically he mentioned in one of the previous episodes one of the (few) features of C++ he likes is function overloading so I would imagine we would see that used in the future.
The specific features he has mentioned are function and operator overloading. IMHO these features definitely help with maintainability when used judicially, but they can be "too much rope" in the wrong hands.

Historically, Microsoft's poor support for C meant you were forced to use C89 which is pretty clunky by modern standards (e.g. declare all variables at beginning of block, etc...). Things appear to have improved with VS 2013 - not quite C99 but a lot better.
Yes, in general, we will be using some C++ features so if you are expecting to be able to run Handmade Hero through a strictly C compiler, you will have to do a fair amount of work. For example, you will need at least operator overloading and function overloading.

- Casey
joekarl

Sure one can get around this by compiling with a C++ compiler but not every platform has (good) C++ compatibility (ie Swift).


You mention Swift, by which I assume you mean the language. I've never used or looked at Swift, but I just want to add that I would approach this problem from the following mindset: Handmade Hero is written in C++ in C-style. If one wants to use another language, you must go into it expecting translation work. Writing in pure C may make translation to some C-like languages easier, but at the cost of the features that C++ provides.

Personally, I have been following along with the D programming language, and I find the translation work to be quite trivial. After the first day, you can simply generate a diff for the next day, and then add those changes in, making whatever modifications you need to make it compile in your language of choice.
Well I think I may have bungled the question up (by leaving out important info).
I wasn't looking for reasons why not to use C++ features in the source, but why the header providing access to the platform independent layer isn't a C compatible header.

Most compilers will process header files based on the filetype that imports them. So a C++ or Objective-C++ file that imports a header will treat it with C++ rules, where a Swift or C or Objective-C file that imports a header will treat it with C rules.
So this would totally work cleanly *if* the header that holds the data types between the platform/platform independent layers defined structs that were C compatible. The handmade.cpp file (and other subsequent cpp and header files) can C++ to their hearts content.

But considering that we're probably not going to change the handmade.h source to make that header exportable to C directly it's probably a moot point.

That said, I think I have this (somewhat) working as is, but I'm having to write an Objective-C++ bridge to be able to access the platform independent layer and then export the Objc++ layer symbols into Swift (which is by no means pretty).
Essentially all I'm doing is defining bridge structs in my Objc++ layer which are exported to Swift which allow memory access to things like the game_memory, game_input, game_offscreen_buffer.

Whew, too many things flying around...

Long story short, this whole process would be immensely easier if the header that contains the typedefs for things flowing between the platform and platform independent layers was C compatible.

I'll shut up now lol and get back to actually getting this to work (need to implement the dylib loading so I can actually get this running).
Oh, OK, I see what you're trying to do. Yeah, that is not a hard thing for us to support. We need to split handmade.h off into game and platform parts anyway, so I can take a little extra time today to set things up to be easier for people who need an import layer.

- Casey
OK, so we pulled out the platform interface code into a separate .h on today's stream, and C-ified it a bit. Please take a look at that and see if that's closer to what you need.

- Casey
That absolutely makes the interop a million times easier.
Worked like a charm.

Thanks Casey!