Trouble with Linking C file to C++ file

Hey,

I have a program that has 5 files, 2 header files called:
1
2
console.h
screen.h

and 3 source files called:
1
2
3
a2main.cpp
screen.cpp
console.c    //not a typo 


When I copy the main from my a2main.cpp file to my screen.cpp my program compiles without a problem. But when I try and compile it using the external main I get the following errors.
1
2
3
4
screen.obj : error LNK2005: _line already defined in a2main.obj
screen.obj : error LNK2005: _cursor_pos already defined in a2main.obj
screen.obj : error LNK2005: _col already defined in a2main.obj
a2main.exe : fatal error LNK1169: one or more multiply defined symbols found

Could someone please explain why I am getting these errors.
Also please note that the variables mentioned in the errors are not used at all in a2main.cpp they were declared in console.c then redeclared in screen.cpp.

I have used:
1
2
3
extern "C" {
   #include "console.h" 
} 

in both my a2main.cpp and screen.cpp as the objects and functions in them are called by the main.

Thanks.
Also please note that the variables mentioned in the errors are not used at all in a2main.cpp they were declared in console.c then redeclared in screen.cpp.

Yes, but where are these variables defined?
They were defined in the console.h file.

The variables were declared in the .c and defined in the .h? That doesn't sound right.
Sorry meant the other way around, they were defined in the.h and declared in the .c and .cpp files.
Please show us the declarations and definitions, along with which file each came from.
Definition for the variables in console.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/* variable definition */
/* line(row) */
#include<string.h>
int line, col, cursor_pos;

#define UNIX 1
#define WINDOWS 2
#define OS WINDOWS /* choose which platform to compile for */


#if OS == UNIX
	/* using Unix/Linux ncurses library only */
	#include <ncurses.h>
#elif OS == WINDOWS
	/* include windows specific libraries */
	#include <conio.h>
	#include <windows.h>
#endif
//There is more code below but its just function definitions. 


Using variables in console.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void console_On(void) {
  #if OS == WINDOWS
     /* no startup requirements for windows */
	line = 5;
	col = 5;
	cursor_pos = 0;
  #elif OS == UNIX
	initscr( );
    noecho( );
    cbreak( );
    keypad(stdscr, 1);
	line = 5;
	col = 5;
	cursor_pos = 0;
  #endif
}
//Once again more code below but the first declaration of the variables is here. 


The declaration of the class:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Field {
   protected:
      char *str_;
      int row_, col_, flen_;
      int slen_, offset_, start_, ctype_, height_;
      static int insert_;

   public:
      Field(char *, int, int, int, int, int=0, int=0, int=1);
      virtual ~Field( );
      void draw( ) const;
	  //int draw(int, int, int, int, char, char, char) const;
      void draw(int, int, int, int, char, char, char) const;
      virtual bool editable( ) const;
      virtual int edit( );
      virtual char* data( );
};

class TextField : public Field {
      private:
         char edge_, top_btm_, ls_rs_;
         char **page_;
         int height_, box_h, width_;

      public:
         TextField(char *, int, int, int, int, char='+', char='-', char='|');
         virtual ~TextField( );
         virtual int edit( );
         virtual bool editable( ) const;
         virtual char* data( );
};


The variables being declared in screen.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//declaring variable line
TextField::TextField(char *page, int row, int col, int width,
                    int height, char edge, char top_btm, char ls_rs) :
                    Field(page, row, col, width, 0, 0, 0, 0) { // sending data to Field base class
	char msg[121];
	int i, j, len = strlen(str_), /*line = 0,*/ count;
	height_ = len/width + 1;          // determining how many 'lines' are in the string 'page'
	box_h = height;
	edge_ = edge;
	top_btm_ = top_btm;
	ls_rs_ = ls_rs;
	page_ =  new char * [height_];    // allocating memory for an array of pointers
	width_ = width;

	line = 0;

//declaring the variables col and cursor_pos
int TextField::edit( ) {
   int i, j/*, line*/;
   char msg[121];
   int keycode = 0;
   int arrayTop = 0, arrayEnd = height_, current = arrayTop;
   int boxTop = 0, boxEnd = box_h-1;//+row_-2;

   console_Box(row_-1, col_-1, flen_+2, box_h+2, edge_, top_btm_, ls_rs_);

   for(i=0; i<box_h; i++){
      console_Move(row_+i, flen_);
      console_Draw(page_[i], row_+i, col_, flen_);
      //console_GetKey( );				// wait for a key press after each line is displayed
   }									// for demonstration purposes only	

   console_Move(row_, col_);
   cursor_pos = 0;
   col = col_;

EDIT: I haven't given the whole function just the parts where the variables are declared.

Hope this helps.
Last edited on
You should not define variables in headers. Variables should only ever be defined in source files and declared (extern) in headers. This is precisely the problem it causes.

A more important point is this: avoid global variables altogether. There should be no need for variable definitions or declarations (save for constants) in headers of well designed C++ code.
Last edited on
Oh I see, so simply changing the console.h to:
1
2
#include<string.h>
extern int line, col, cursor_pos;

should solve the problem right?

What if I use the same variable names in a class declaration like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class TextField : public Field {
      private:
         char edge_, top_btm_, ls_rs_;
         char **page_;
         int height_, box_h, width_;
         int line, col, cursor_pos //using the same variable names as declared in console.h

      public:
         TextField(char *, int, int, int, int, char='+', char='-', char='|');
         virtual ~TextField( );
         virtual int edit( );
         virtual bool editable( ) const;
         virtual char* data( );
};
Are these global variables actually used anywhere? If so, you will need to define them in a source file.

The member variables will hide the globals in the TextField class.
The variables are used extensively in the console.c file but I used them in my screen.cpp as they would make the code more readable.

I fixed the code accordingly and so far so good nothing seems to be broken.

Thanks a lot.
Topic archived. No new replies allowed.