7

I'm trying to create a simple C++ test application based off Qt 5.1 configure KMS functional test (qtbase/config.tests/qpa/kms), which is failing. The application is very simple as shown below:

#include <stdlib.h>
extern "C" {
#include <gbm.h>
#include <xf86drmMode.h>
#include "xf86drm.h"
}
#include <EGL/egl.h>
#include <GLES2/gl2.h>

int main(int, char **)
{
    // Check for gbm_surface which is quite a recent addition.
    gbm_surface *surface = 0;

    return 0;
}

The problem is that when including "libdrm/xf86drmMode.h" or "libdrm/xf86drm.h", "drm/drm.h" is also included. Within "drm.h" there is a structure defined as:

struct drm_buf_map {
    int count;              /**< Length of the buffer list */
    void *virtual;              /**< Mmap'd area in user-virtual */
    struct drm_buf_pub *list;   /**< Buffer information */
};

Notice the variable named "virtual" within the drm_buf_map structure. This causes a C++ compiler error, which cannot be resolved by using extern "C". This makes sense, but I'm not sure how to go about solving this problem (other than using the C compiler). Is there a compiler flag to handle this?

Thanks!

László Papp
  • 51,870
  • 39
  • 111
  • 135
Michael
  • 115
  • 1
  • 4

2 Answers2

3

Here's a possible solution:

Add #define virtual blah_blah_blah before the include

Add #undef virtual after the include

Edit

Now if you need to use the member virtual you will have to call it blah_blah_blah.

rabensky
  • 2,864
  • 13
  • 18
  • What about the library (either static/dynamic library) which uses the symbol `virtual`? Your #define would not replace that. – Nawaz Sep 26 '13 at 17:37
  • 2
    @Nawaz But they are already compiled. So it doesn't matter. It isn't a function name, it's a variable name which are mutable. But the best answer would be from OP - telling us if it worked :p – rabensky Sep 26 '13 at 17:43
  • Linker wouldn't be able to link them if they're different. The whole purpose of using `extern "C"` is to help the linker (and the compiler). – Nawaz Sep 26 '13 at 17:44
  • This is technically undefined behaviour. – Simple Sep 26 '13 at 17:45
  • @Nawaz only for globally defined variables. Not for memeber / local variables. It's like when you define a function in the header `void foo(int num);` but in the implementation you use `void foo(int x);`. It doesn't matter. AFAIK the compiled code doesn't keep these names. – rabensky Sep 26 '13 at 17:47
  • @cluracan: It does matter; the members are looked up as well. – Nawaz Sep 26 '13 at 17:48
  • @Nawaz - just tested it myself. It doesn't matter. Members are only saved by their offsets. There is not need to create name bindings where they aren't needed. – rabensky Sep 26 '13 at 17:52
  • As static libraries are outside the scope of the standard there's no hard rule, but I would say that having a different name for a member would be an ODR violation. – Simple Sep 26 '13 at 17:54
  • 1
    Code is compiling with no errors. Seems like a reasonable solution for this scenario. – Michael Sep 26 '13 at 17:57
  • OK, lets say it like this: It is against the standard (probably). But it works. It may not work in future versions of C. And @Michael - be aware it might break in the future if someone changes the way code it compiled (but that is true of most code...) – rabensky Sep 26 '13 at 17:58
3

The real issue here is that you are including a wrong drm.h. You are not using a package manager and also do not specify /usr/include/libdrm in the include path. If one of these two is not done, the compiler is going to pick up /usr/include/drm.h or another that has this issue. But the file from libdrm (/usr/include/libdrm/drm.h) has this fixed.

Refer to the real drm.h file — that already has Eric’s patch for this 4 years back:

struct drm_buf_map {
int count;  /**< Length of the buffer list */
#ifdef __cplusplus
void *virt;
#else
void *virtual;  /**< Mmap'd area in user-virtual */
#endif
struct drm_buf_pub *list;   /**< Buffer information */
};
Greg Bacon
  • 134,834
  • 32
  • 188
  • 245
Prabindh
  • 3,356
  • 2
  • 23
  • 25