Strange multiple definitions error with headers - c++

I have a strange multiple definitions error in my project.
I'm using the #ifndef preprocessor command to avoid including the same file multiple times. I cleared all other code. Here are my simplified files:
1 - main.cpp
#include "IP.hpp"
int main()
{
return 0;
}
2 - IP.cpp
#include "IP.hpp"
//some codes!
3 - IP.hpp
#ifndef IP_HPP_INCLUDED
#define IP_HPP_INCLUDED
unsigned char LUTColor[2];
#endif // IP_HPP_INCLUDED
Using codeblocks & gnu gcc in win7, it says:
obj\Debug\main.o:C:\Users\aaa\Documents\prg\ct3\main.cpp|4|first defined here|
||=== Build finished: 1 errors, 0 warnings ===|
Before I deleted all of the other code, the error was:
||=== edgetest, Debug ===|
obj\Debug\IP.o||In function `Z9getHSVLUTPA256_A256_12colorSpace3b':|
c:\program files\codeblocks\mingw\bin..\lib\gcc\mingw32\4.4.1\include\c++\exception|62|multiple definition of `LUTColor'|
obj\Debug\main.o:C:\Users\aaa\Documents\prg\edgetest\main.cpp|31|first defined here|
||=== Build finished: 2 errors, 0 warnings ===|
And 'LUTColor' is in IP.hpp !
What's wrong?

The problem is in the header - you need:
#ifndef IP_HPP_INCLUDED
#define IP_HPP_INCLUDED
extern unsigned char LUTColor[2]; // Declare the variable
#endif // IP_HPP_INCLUDED
Do not define variables in headers!
You also need to nominate a source file to define LUTColor (IP.cpp is the obvious place).
See also: What are extern variables in C, most of which applies to C++ as well as C.

Related

Variable has incomplete type in class definition?

I've got this class definition in a .h file, and the implementation in a .cpp file. When I try to compile this, the header file gives some errors and warnings:
/home/don/BerthaApex/apex/src/lib/apexmain/apexloader.h:6: error: variable 'APEX_EXPORT ApexLoader' has initializer but incomplete type
class APEX_EXPORT ApexLoader
^
/home/don/BerthaApex/apex/src/lib/apexmain/apexloader.h:6: warning: extended initializer lists only available with -std=c++11 or -std=gnu++11 [enabled by default]
/home/don/BerthaApex/apex/src/lib/apexmain/apexloader.h:9: error: expected primary-expression before 'public'
public:
The code in which this error occurs is:
#ifndef _APEXLOADER_H
#define _APEXLOADER_H
#include "global.h"
class APEX_EXPORT ApexLoader
{
public:
int Load( int argc, char *argv[]);
};
#endif
With the "class APEX_EXPORT ApexLoader" being the line with the error and the warning.
The APEX_EXPORT is defined in a header file that is included from this same file.
EDIT:
The APEX_EXPORT is defined in "global.h" as follows:
#ifdef APEX_MAKEDLL
#define APEX_EXPORT APEX_EXPORT_DECL
#else
#define APEX_EXPORT APEX_IMPORT_DECL
#endif
Does anyone know why these errors are there? And how can I get rid of them?
Thank you in advance!
Compiler: gcc 4.8.4
OS: Ubuntu 14.04
My psychic debugging skills tell me that APEX_EXPORT isn't #defined and thus the compiler thinks you're trying to declare a variable of that type.
If you think you've included all the right headers the best way to go is to just run the preprocessor on your source file and see what it generates (for example g++ -E).

Is it possible to define a macro from a macro

Here is what I am thinking.
#define prefix_1 1
#define prefix_2 2
#define prefix_3 3
And I want to define a macro using the prefixes above — like macro macro_prefix_1 macro_prefix_2 — and I expect them to turn into macro_1 macro_2, etc. Just like the code below
#define macro_##prefix_1 I_am_macro_1
#define macro_##prefix_2 I_am_macro_2
Is this possible?
Unfortunately, what you are trying to do is impossible. The (##) directive is impossible to use within a macro declaration. It is only possible to use it within the definition as such.
#define glue(a,b) a ## b
glue(c,out) << "test";
Example borrowed from cplusplus.com
Below, I have written an example of what you want to do.
#include <stdio.h>
#define prefix_1 1
#define prefix_2 2
#define prefix_3 3
#define macro_##prefix_1 "macro_1"
#define macro_##prefix_2 "macro_2"
#define macro_##prefix_3 "macro_3"
int main(){
printf("%s\n%s\n%s\n", macro_prefix_1, macro_prefix_2, macro_prefix_3);
return 0;
}
When you try to compile the above code you will get this build log.
||=== Build: Debug in file_test (compiler: GNU GCC Compiler) ===|
main.cpp|7|warning: missing whitespace after the macro name [enabled by default]|
main.cpp|7|error: '##' cannot appear at either end of a macro expansion|
main.cpp|8|warning: missing whitespace after the macro name [enabled by default]|
main.cpp|8|error: '##' cannot appear at either end of a macro expansion|
main.cpp|9|warning: missing whitespace after the macro name [enabled by default]|
main.cpp|9|error: '##' cannot appear at either end of a macro expansion|
main.cpp||In function 'int main()':|
main.cpp|13|error: 'macro_prefix_1' was not declared in this scope|
main.cpp|13|error: 'macro_prefix_2' was not declared in this scope|
main.cpp|13|error: 'macro_prefix_3' was not declared in this scope|
||=== Build failed: 6 error(s), 3 warning(s) (0 minute(s), 0 second(s)) ===|
So if you want to be able to have macro's you will just have to add the prefix normally. Luckily you were basically already doing this, but adding "##". Hope this helped.

Creating a Makefile for C++ and C source code [duplicate]

I'm getting an undefined referenced error, not knowing the reason why.
So I have 2 files which makes a static lib : keyboard_input.c, keyboard_input.h
Here's the content of the .h file:
#ifndef __MOD_KBINPUT__
#define __MOD_KBINPUT__
int kbInit();
int kbWait();
int kbTest();
#endif
And the CMakeLists.txt file looks like this:
FILE(
GLOB_RECURSE
sources
*.c
)
INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/include/utils/kbreader")
ADD_LIBRARY(keyboardReader ${sources})
Compiling this lib gives some warnings:
src/utils/kbreader/keyboard_input.c: In function ‘kbInit’:
src/utils/kbreader/keyboard_input.c:13:14: warning: assignment from incompatible pointer type [enabled by default]
src/utils/kbreader/keyboard_input.c: In function ‘kbWait’:
src/utils/kbreader/keyboard_input.c:21:55: warning: passing argument 4 of ‘fread’ from incompatible pointer type [enabled by default]
/usr/include/stdio.h:708:15: note: expected ‘struct FILE * __restrict__’ but argument is of type ‘struct FILE *’
Now, for my main executable (main.cpp):
#include <keyboard_input.h>
int main()
{
kbTest();
return 0;
}
Processed by the following CMakeLists.txt file:
include_directories("${PROJECT_SOURCE_DIR}/include/utils/kbreader")
file(
GLOB_RECURSE
srcs
*.cpp
)
add_executable(
PEM
${srcs}
)
target_link_libraries(PEM keyboardReader)
Ends up getting that error:
CMakeFiles/PEM.dir/main.cpp.o: In function `main':
main.cpp:(.text+0xb): undefined reference to `kbTest()'
collect2: ld returned 1 exit status
make[2]: *** [src/PEM/main2/PEM] Error 1
make[1]: *** [src/PEM/main2/CMakeFiles/PEM.dir/all] Error 2
The libkeyboardReader.a is created, and the kbTest() function doesn't do anything except
{return 0; }
If I set the definition of kbTest() in the header file, it works.
But there's something i don't get, when i type: make keyboardReader here is the output:
[ 73%] Building C object src/utils/kbreader/CMakeFiles/KeyboardReader.dir/keyboard_input.c.o
[Warning explained above]
Linking C static library ../../../lib/libKeyboardReader.a
Is there something wrong? Does the note error message makes my lib omit the keyboard_input.c file?
You're mixing C and C++ files. To make that work, you just have to tell the C++ compiler that it's calling a C function, by changing the header file like so:
#ifndef MOD_KBINPUT
#define MOD_KBINPUT
/* note I also fixed the macro so you aren't using a system-reserved name */
#if __cplusplus
/* this is the important part */
extern "C" {
#endif
int kbInit();
int kbWait();
int kbTest();
#if __cplusplus
}
#endif
#endif
Otherwise the C++ compiler assumes the function will be given a C++ internal name (which encodes all the type information in the signature, this is what lets the linker distinguish between overloaded functions) and then the linker doesn't find it.

Compiling a class with separate source and header

EDIT: the solution to the problem is the following: http://www.jusuchyne.com/codingchyne/2011/03/codeblocks-failed-to-find-the-header-file/
It won't compile, I have the following errors:
foo.h no such file in directory;
foo has not been declared;
num was not declared in this scope
foo is not a class or a namespace
It is odd, to say the least, because I just used the code blocks "Create a new Class" and then added it to this project. This is the source code:
Header:
#ifndef FOO_H
#define FOO_H
class foo
{
private:
int num;
public:
foo();
void set_num(int set);
int get_num();
};
#endif // FOO_H
the cpp
#include "foo.h"
foo::foo()
{
num = 10;
}
void foo :: set_num(int set)
{
num = set;
}
int foo :: get_num()
{
return num;
}
Disregard the calss itself and what it does, the problem is that it doesn't compile even though I used the default code blocks class creation setting.
The errors:
C:\Users\SameTime\Desktop\CodeBLocks\ASDD\src\foo.cpp|1|error: foo.h: No such file or directory|
C:\Users\SameTime\Desktop\CodeBLocks\ASDD\src\foo.cpp|3|error: 'foo' has not been declared|
C:\Users\SameTime\Desktop\CodeBLocks\ASDD\src\foo.cpp|3|error: ISO C++ forbids declaration of 'foo' with no type|
C:\Users\SameTime\Desktop\CodeBLocks\ASDD\src\foo.cpp||In function 'int foo()':|
C:\Users\SameTime\Desktop\CodeBLocks\ASDD\src\foo.cpp|5|error: 'num' was not declared in this scope|
C:\Users\SameTime\Desktop\CodeBLocks\ASDD\src\foo.cpp|6|warning: no return statement in function returning non-void|
C:\Users\SameTime\Desktop\CodeBLocks\ASDD\src\foo.cpp|8|error: 'foo' is not a class or namespace|
C:\Users\SameTime\Desktop\CodeBLocks\ASDD\src\foo.cpp||In function 'void set_num(int)':|
C:\Users\SameTime\Desktop\CodeBLocks\ASDD\src\foo.cpp|10|error: 'num' was not declared in this scope|
C:\Users\SameTime\Desktop\CodeBLocks\ASDD\src\foo.cpp|13|error: 'foo' is not a class or namespace|
C:\Users\SameTime\Desktop\CodeBLocks\ASDD\src\foo.cpp||In function 'int get_num()':|
C:\Users\SameTime\Desktop\CodeBLocks\ASDD\src\foo.cpp|15|error: 'num' was not declared in this scope|
||=== Build finished: 8 errors, 1 warnings ===|
If the header is not in the same directory you must either specify the path in the include command, or you must add -I Path directive to your makefile or include settings.
Maybe this link also helps as codeblock seems to have problems.
http://www.jusuchyne.com/codingchyne/2011/03/codeblocks-failed-to-find-the-header-file/
This should be a comment, but I don't have 50 rep yet...
Can you navigate to the source directory in the command line and try to compile manually to ensure that the error isn't with the IDE?
If your IDE is using g++ (it probably is) then the command would be g++ foo.cpp
Open Windows Explorer
Navigate to the folder containing the files
Make sure the header is called "foo.h" (You know Explorer sometimes hides file extensions, right?)
If that doesn't do it, your compiler is broken.

Unexpected undefined reference

I'm getting an undefined referenced error, not knowing the reason why.
So I have 2 files which makes a static lib : keyboard_input.c, keyboard_input.h
Here's the content of the .h file:
#ifndef __MOD_KBINPUT__
#define __MOD_KBINPUT__
int kbInit();
int kbWait();
int kbTest();
#endif
And the CMakeLists.txt file looks like this:
FILE(
GLOB_RECURSE
sources
*.c
)
INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/include/utils/kbreader")
ADD_LIBRARY(keyboardReader ${sources})
Compiling this lib gives some warnings:
src/utils/kbreader/keyboard_input.c: In function ‘kbInit’:
src/utils/kbreader/keyboard_input.c:13:14: warning: assignment from incompatible pointer type [enabled by default]
src/utils/kbreader/keyboard_input.c: In function ‘kbWait’:
src/utils/kbreader/keyboard_input.c:21:55: warning: passing argument 4 of ‘fread’ from incompatible pointer type [enabled by default]
/usr/include/stdio.h:708:15: note: expected ‘struct FILE * __restrict__’ but argument is of type ‘struct FILE *’
Now, for my main executable (main.cpp):
#include <keyboard_input.h>
int main()
{
kbTest();
return 0;
}
Processed by the following CMakeLists.txt file:
include_directories("${PROJECT_SOURCE_DIR}/include/utils/kbreader")
file(
GLOB_RECURSE
srcs
*.cpp
)
add_executable(
PEM
${srcs}
)
target_link_libraries(PEM keyboardReader)
Ends up getting that error:
CMakeFiles/PEM.dir/main.cpp.o: In function `main':
main.cpp:(.text+0xb): undefined reference to `kbTest()'
collect2: ld returned 1 exit status
make[2]: *** [src/PEM/main2/PEM] Error 1
make[1]: *** [src/PEM/main2/CMakeFiles/PEM.dir/all] Error 2
The libkeyboardReader.a is created, and the kbTest() function doesn't do anything except
{return 0; }
If I set the definition of kbTest() in the header file, it works.
But there's something i don't get, when i type: make keyboardReader here is the output:
[ 73%] Building C object src/utils/kbreader/CMakeFiles/KeyboardReader.dir/keyboard_input.c.o
[Warning explained above]
Linking C static library ../../../lib/libKeyboardReader.a
Is there something wrong? Does the note error message makes my lib omit the keyboard_input.c file?
You're mixing C and C++ files. To make that work, you just have to tell the C++ compiler that it's calling a C function, by changing the header file like so:
#ifndef MOD_KBINPUT
#define MOD_KBINPUT
/* note I also fixed the macro so you aren't using a system-reserved name */
#if __cplusplus
/* this is the important part */
extern "C" {
#endif
int kbInit();
int kbWait();
int kbTest();
#if __cplusplus
}
#endif
#endif
Otherwise the C++ compiler assumes the function will be given a C++ internal name (which encodes all the type information in the signature, this is what lets the linker distinguish between overloaded functions) and then the linker doesn't find it.