Live data from Hacker News

How to write better game libraries

handmade.network

41–50 of 129 posts

Re: How to write better game libraries

#41
As a warning: While C99 is a really nice language - especially over C89 - please note that the Visual Studio C compiler still does not support the full C99 specification, and it is not possible at all to compile C99 as C++ code (which sometimes is useful).

I usually recommend to write library-level code in the "subset of C99 which compiles both in C and C++ mode on GCC, clang and MSVC". This is basically a version of C that's somewhere C89 and C99 (basically a "C95").

Another quite valid option is to define a pure C-API first, but implement the "inner library code" in a simple C++ (just be careful with "modern C++", since this usually results in increased compilation time and binary size).

Re: How to write better game libraries

#42

Make is a much the lingua franca of build systems as C is for programming, so there's no reason not to provide a (simple) makefile. The alternative they suggest is worse anyway.

Windows is the reason make is not a good choice. Visual Studio is a de-facto standard for Windows development and it's not exactly makefile-oriented.

The lowest common denominator for build instructions that works everywhere is literally "set your include paths like so and compile these sources".

Re: How to write better game libraries

#43

This is bad advice on the c++ part. If you don't use RAII, then you could've just not done the c++ lib (and have just a c lib). Exceptions, raii and smart pointers are what makes modern c++ so pleasant, next to templates.

> modern C++ > pleasant Nice joke. Hour-long compilations, type-unsafe templates with unreadable errors, and circular references are considered pleasant now?

- reasonable organized code doesn't take hours. even template heavy code is quite fast these days

- templates are type safe. it is just the error messages are not helpful a lot of times. C++20's concepts should help

- circular references. that's a thing in C as well. as soon as you need interact with your libraries user to allocate/deallocate resources.

C++ has a large surface to interact with. Yes you can shot yourself in your foot. However, the more you know you can use the features to your advantage instead of shotting yourself in the foot. At the point you gain more than you lose.

Re: How to write better game libraries

#45

Some of these recommendations are awesome, others aren’t good, IMO. > Always prefix your names to avoid name collisions Solved by C++ namespaces. > Use header guards instead of #pragma once. #pragma once is supported by all mayor compilers, header guards can introduce bugs, also #pragma once builds measurably faster: https://github.com/electronicarts/EASTL/blob/3.15.00/include... > Expose constants to the user using…

> Solved by C++ namespaces. I've never understood what's the practical difference between NS::foo() and NS_foo() with regards to preventing name collisions. Can someone enlighten me? I know some disadvantages of the namespacing variant, though. There are now multiple names for the items defined in the namespace: the qualified one and the unqualified one. The latter is often not unique in practice, since the programme…

> what's the practical difference between NS::foo() and NS_foo() with regards to preventing name collisions.

They both do the job. There’re 2 practical differences.

1. You can write `using namespace` inside functions or the whole .cpp files. This often makes the consuming code more readable.

2. Sometimes you want to replace implementations. With prefixes it gonna be massive changes likely to introduce new bugs. With namespaces, replace `using std::vector` with `using eastl::vector` and you’re done.

> Even more often, I want to iterate over the values of an enum.

I only need to do that rarely. When I do, I cast types like this:

    enum struct eParamKind : uint8_t
    {
        Bla, Blub, Foo, valuesCount
    };
    for( uint8_t i = 0; i 
> I won't let programming ergonomics be ruined in the name of "type safety".

I disagree on ergonomics. VS makes much easier to consume API with strongly typed enums: ePar::f, to type eParamKind::Foo It’s similar with namespaces versus prefixes BTW, IDE will first auto-complete the namespace, then only list members of that namespace once you type the `::`

Update: another C++ feature relevant for game development is overloaded operators. Games often do non-trivial amount of math on small vectors, matrices and quaternions. Overloaded operators make sense for them.

Re: How to write better game libraries

#46

As a warning: While C99 is a really nice language - especially over C89 - please note that the Visual Studio C compiler still does not support the full C99 specification, and it is not possible at all to compile C99 as C++ code (which sometimes is useful). I usually recommend to write library-level code in the "subset of C99 which compiles both in C and C++ mode on GCC, clang and MSVC". This is basically a version of…

The one feature from C99 that I rely on (from the top of my head) is designated initializers which is still not in C++...

    enum {
        FPGAPARAM_FOO,
        FPGAPARAM_BAR,
        FPGAPARAM_BAZ,
        NUM_FPGAPARAM_KINDS
    };

    struct FpgaparamInfo {
        const char *name;
        int address;
        int args;
    };

    static struct FpgaparamInfo fpgaParamInfo[NUM_FPGAPARAM_KINDS] = {
        [FPGAPARAM_FOO] = { "FOO", 0x1337, -1 },
        [FPGAPARAM_BAR] = { "BAR", 0x666, -1 },
        [FPGAPARAM_BAZ] = { "BAZ", 0x42, -1 },
    };
The FpgaParamInfo is basically a mapping from a FPGAPARAM_??? value to additional information. We can make as many of these mappings as we want, and can define them where we want, which means it's all nicely modular. That's not really possible when modelling in a OOP fashion.

I really like this style of programming since it's data first and it minimizes the amount of actual code. Designated initializers are important because the order in which the items in "fpgaParamInfo" are given doesn't matter. Without designated initializers, programming in this style would probably lead to many hard to find bugs when the enum is changed and not all associated data items are updated.

Re: How to write better game libraries

#47
post #21

Earlier quoted context omitted.

Other than UNIX like kernels and tiny PIC micro-controllers no one else should still be programming in straight C in 21st century.

If people choose to and it gives them joy, and they are productive and even learn valuable things, why not let them be?

Because if someone else happens to use that library, it might blow up on their face, e.g. WhatsApp dependency on android-gif-drawable.

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-1193...

Re: How to write better game libraries

#48

Earlier quoted context omitted.

> Solved by C++ namespaces. I've never understood what's the practical difference between NS::foo() and NS_foo() with regards to preventing name collisions. Can someone enlighten me? I know some disadvantages of the namespacing variant, though. There are now multiple names for the items defined in the namespace: the qualified one and the unqualified one. The latter is often not unique in practice, since the programme…

> what's the practical difference between NS::foo() and NS_foo() with regards to preventing name collisions. They both do the job. There’re 2 practical differences. 1. You can write `using namespace` inside functions or the whole .cpp files. This often makes the consuming code more readable. 2. Sometimes you want to replace implementations. With prefixes it gonna be massive changes likely to introduce new bugs. With…

Code completion works very well with plain identifiers. No need for namespaces.

> replace `using std::vector` with `using eastl::vector` and you’re done.

The pipe dream of reusability.. If I ever happen to be in a situation where that will work, I'll happily use a text replace to change my identifiers. Or just link a different library if it has the same names.

Re: How to write better game libraries

#49

It always baffles me when a library comes with its own arcane build code. Instructions like "Requires Python" invariably turn out to actually mean "Requires hours of debugging".

IMO the ideal way to get your library used is to generate a single .h and .c file.

Re: How to write better game libraries

#50
post #47

Earlier quoted context omitted.

If people choose to and it gives them joy, and they are productive and even learn valuable things, why not let them be?

Because if someone else happens to use that library, it might blow up on their face, e.g. WhatsApp dependency on android-gif-drawable. https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-1193...

[deleted]
Post reply on HN