0

I have a code in which I #include<linux/videodev2.h>. There are three files:

  1. one header file- includes: stdint.h and stdlib.h. Defines a couple of functions, a struct, say abc, and some #define macros. One of the functions is

    int func(int, uint32_t, size_t, abc*);
    
  2. one cpp file with a lot of methods, including definition of the functions in the .h file.

  3. one main.cpp which has main() which has a function call to the method in the .h file (complete file below). This file is only for testing purposes.

    #include "head.h"
    int main() {
        func(5, (uint32_t)5, (size_t)5, 0);
        return 0;
    }
    

What is see is a curious case:

  1. If I include linux/videodev2.h only in .h file, uint32_t and other things defined in this header are not accessible by the .cpp files. (erros I get are: uint32_t was not declared in this scope, and uint32_t does not name a type, among others). This happens even if the first line of the .h file is #include<linux/videodev2.h>
  2. If I include the videodev2 header in both the cpp files, it works only if I import it (videodev2) before the .h file.
  3. If I use func(5, (uint32_t)5, (size_t)5, (abc*)0); in the main.cpp file, I get the error that abc is not declared in this scope.

I am compiling using the command: g++ main.cpp head.cpp

I am unable to figure out why is this. I would like to include the videodev2 header in the .h file since, it is almost certain that the code using the .h file will be dependent on it. But it seems that including it in .h file has no effect at all.

I must be honest here. This was C code which I had to convert to C++. I know that I am not conforming to the best practices and standards. But why is this behaviour seen?

Deepanshu
  • 806
  • 6
  • 6
  • I don't know what did it, but I moved the three files to a new directory. And it compiled flawlessly. There are a lot of files in the old directory. Do any of you have any suggestion as to why the presence of some other file affect this? – Deepanshu Oct 30 '12 at 03:55

2 Answers2

3

Remember that the #include directive indicates to the preprocessor the contents of the specified file should be treated as if they appeared directly in the source file in place of the directive (paraphrased from MSDN).

With that in mind, it seems like you are encountering improper order of #includes and also missing #includes. My guess would be that you are not including your own header file in your .cpp files. This would explain cases one and three. Consider the following files:

// header.h
// #include <linux/videodev2.h>  <-- Option 1
class A {
    void func(uint32_t var);
};

// header.cpp
void A::func(uint32_t var) {
    // implementation
}

// main.cpp
// #include <linux/videodev2.h>  <-- Option 2
#include "header.h"
// #include <linux/videodev2.h>  <-- Option 3

int main() {
    // implementation; something creates an instance of A and calls func
}

Now, Option 1 is not exactly desirable; it's good practice to avoid #includes in header files because they can increase build times and create unwanted dependencies. However, it will ensure that the types header.h requires are there for it to use. The essential bit is that the contents of linux/videodev2.h have to appear before the contents of header.h, anywhere that header.h is #included.

This brings me to Option 2. Option 2 will also compile correctly, because linux/videodev2.h is included before your header, and your header relies on types defined in it. Also important is that both main.cpp and header.cpp must #include "header.h", because they reference symbols declared in it.

If you were to go with Option 3, you would get compilation errors that the type uint32_t is not defined, and the compiler would point to your header file. This is because the contents of the header file appear before the contents of linux/videodev2.h, and so the compiler does not yet understand what the type uint32_t is when it encounters it.

So, given all that, you have choices: include `linux/videodev2.h' before each include of your own header file, or include it directly in your header file. I mentioned earlier that the latter is not good practice, but for your particular case, it might be the better option of the two, in case your header file needs to be included in many .cpps.

I think this would be a good opportunity to dive into precompiled headers, but I'm not as well-versed in them, so I'd leave it to someone who has more experience to explain them.

Hope this helps :)

Community
  • 1
  • 1
kevintodisco
  • 5,061
  • 1
  • 22
  • 28
  • 1
    Thanks for your detailed reply. Really appreciate it. But I figured that just moving the three files to a clean directory worked. Is there some reason why some other files present in the old directory cause this problem? – Deepanshu Oct 30 '12 at 03:58
0

Found the answer. There was .h.gch file in the directory. I didn't know about precompiled header. Thanks ktodisco for the insight. I still have no idea why that file was there in the first place.

Deepanshu
  • 806
  • 6
  • 6