raysan5 / raylib

A simple and easy-to-use library to enjoy videogames programming
http://www.raylib.com
zlib License
21.99k stars 2.22k forks source link

[raylib] raylib.h cannot be included from C++ projects that include cstdio #3747

Closed diath closed 8 months ago

diath commented 8 months ago

Issue description

Raylib currently cannot be included by a C++ project that later includes cstdio (either directly, or indirectly by another library such as fmt in my case). The culprit appears to be the include of stdarg.h in raylib.h. Commenting out the stdarg.h include in raylib.h and the tracelog function makes it possible to compile programs using raylib that include cstdio. Perhaps we could get a define like #define RAYLIB_NO_TRACELOG that can be defined before including raylib.h that removes the tracelog functionality and allows for including it in C++ projects that use cstdio.

Code Example

The following code compiles fine:

#include <cstdio>

namespace raylib {
extern "C" {
#include <raylib.h>
}
}

int main(int, char **)
{
    return 0;
}

The following code does not compile:

namespace raylib {
extern "C" {
#include <raylib.h>
}
}

#include <cstdio>

int main(int, char **)
{
    return 0;
}

With a number of errors coming from the cstdio header:

/usr/include/stdio.h:376:54: error: ‘__gnuc_va_list’ has not been declared
  376 | extern int vprintf (const char *__restrict __format, __gnuc_va_list __arg);
      |                                                      ^~~~~~~~~~~~~~
/usr/include/stdio.h:379:22: error: ‘__gnuc_va_list’ has not been declared
  379 |                      __gnuc_va_list __arg) __THROWNL;
      |                      ^~~~~~~~~~~~~~
/usr/include/stdio.h:388:56: error: ‘__gnuc_va_list’ has not been declared
  388 |                       const char *__restrict __format, __gnuc_va_list __arg)
Peter0x44 commented 8 months ago

This is not a raylib bug

This is because of the namespaces. Including standard library headers inside a namespace doesn't work in this case, because the type definitions in the header will be inside the namespace as well, and can't be accessed from global scope. You can fix this by first including cstdarg before raylib.h Example: https://github.com/raylib-extras/extras-cpp/blob/main/raylib_namespace.h

Everything also works totally fine if you remove the namespace, because then the types will be in the global namespace as expected.

I don't think there's a way for this to be fixed. Just include the header before, this define is totally unnecessary and a horrible idea.