convert C to C++ project

Go To Last Post
17 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm design menus for my device. Each menu has a title, some main options and two menu-navigation options.

Implementing such thing using OOP structure is really easy. So I decided to convert my project from C to C++. I created new C++ project, copied all files to this project while maintaining directory structure and added them to the project. Code compiled successfully while extensions were ".c" but after I change them to ".cpp", compiler started generating multiple strange "undefined reference" and "multiple definition" errors.

  1. Should I migrate to C++ at all? If no, why? How should I achieve my goal in C?
  2. Why these errors appear after I change extensions to ".cpp"? I've read somewhere if I define a variable in a header file and include it in two files, C++ compiler generates two copies of them and linker gets confused. Why this doesn't happen in C? "undefined reference" errors are related to HD44780 and Accurate Delay C libraries.
This topic has a solution.

Slow and Steady!

Last Edited: Fri. Oct 16, 2020 - 09:36 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Don't mess with the libraries, keep them as C files, and change only your own files to C++.

 

In your files, you may need to use 'extern "C"' to include the library headers, for example:

 

extern "C" {
#include "hd44780.h"
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

pajuhesh80 wrote:
Code compiled successfully while extensions were ".c"

That's because the compiler sees the .c extensions, and compiles the files as plain 'C'

 

pajuhesh80 wrote:
after I change them to ".cpp", compiler started generating multiple strange "undefined reference" and "multiple definition" errors

That's because the compiler sees the .cpp extensions, and compiles the files as C++

 

C++ is not quite a proper superset of 'C' - so you must've hit something(s) that 'C' allows, but C++ doesn't

 

Recent example: https://www.avrfreaks.net/commen...

 

EDIT - and another: https://www.avrfreaks.net/commen...

 

But C++ is perfectly capable of interworking with 'C' - so, as  El Tangas says, leave your .c files as 'C' and just link to them via extern "C" ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Oct 7, 2020 - 01:44 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would simply rename the .c files as .cpp and see what happens. If it's well written C it should just compile as C++ anyway and this avoids having to use extern "C" interworking as everything is now C++

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

but he said that gave errors:

pajuhesh80 wrote:
after I change them to ".cpp", compiler started generating multiple strange "undefined reference" and "multiple definition" errors

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Oct 7, 2020 - 02:05 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:
but he said that gave errors:
So tell us what the errors were and we'll fix them.

 

In fact what he said was:

pajuhesh80 wrote:
multiple strange "undefined reference" and "multiple definition" errors.
if it's all C++ then name mangling does not explain undefs. The multiple defs sound a lot like code/data in .h when it's supposed to be in .c/.cpp

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

You could ZIP up your AS7.0 C project and attach the ZIP.

 

Then we could see what the problem(s) might be.

 

You either rename each C file as .CPP

Or you leave as C files but declare references as extern "C" to any CPP files. 

 

We could show you both approaches.

The second method is preferable for re-usable library code.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:
The multiple defs sound a lot like code/data in .h when it's supposed to be in .c/.cpp

Indeed - but then why did it build OK as pure 'C' ?

 

@ pajuhesh80: you have a choice:

  1. Leave the 'C' code as-is, and access it via extern "C";
  2. Fix the issues which arrise after renaming the .c files to .cpp

 

For the latter, as clawson says, you're going to have to give full details of the code and the errors that you're getting before anyone is going to be able to help you with them.

 

To get full details of the error messages, be sure to use the AS 'Output' window;

See: https://www.avrfreaks.net/commen...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:
You could ZIP up your AS7.0 C project and attach the ZIP.

also zip up the C++ project;  so that we can see what you actually did - and any problems with that.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

pajuhesh80 wrote:
Should I migrate to C++ at all?

How well do you know C++ ?

 

As with 'C', if you're not already proficient, it would probably be easier to learn the language on a PC - rather than on a small embedded micro.

 

pajuhesh80 wrote:
How should I achieve my goal in C?

Plenty of examples available of menu systems implemented in 'C' ...

 

pajuhesh80 wrote:
Each menu has a title, some main options and two menu-navigation options

In 'C' - a struct ... ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

1- How well do you know C++ ?

2- Plenty of examples available of menu systems implemented in 'C' ...

3- In 'C' - a struct ... ?

  1. I know it well. But I always had problems when I wanted to use multiple source files in a single C/C++ project.
  2. I saw them. They're good; but most of them don't meet my needs.
  3. Good idea. But maybe I want to add a function to each menu and structs don't support it. (maybe use function pointers?)

 

I attached my project to this post.

Attachment(s): 

Slow and Steady!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

pajuhesh80 wrote:
I know it well. But I always had problems when I wanted to use multiple source files in a single C/C++ project.

that is rather a basic thing

 

most of them don't meet my needs.

In what way(s), exactly ?

 

 I want to add a function to each menu and structs don't support it. (maybe use function pointers?)

Of course function pointers.

 

 

I attached my project to this post.

Which one is it - the original 'C', or the C++ ?

 

EDIT

 

So it's just the C++.

 

As noted earlier, it would be good to also the one that "worked" - before you changed it.

 

The errors are all linker errors:

		Invoking: AVR8/GNU Linker : 5.4.0
		"C:\Program Files (x86)\Atmel\Studio\7.0\7.0\toolchain\avr8\avr8-gnu-toolchain\bin\avr-g++.exe" -o Display.elf  Delay/adelay.o LCD/hd44780.o main.o Menus/_main.o   -Wl,-Map="Display.map" -Wl,--start-group -Wl,-lm  -Wl,--end-group -Wl,--gc-sections -mmcu=atmega328p -B "C:\Program Files (x86)\Atmel\Studio\7.0\7.0\Packs\Atmel\ATmega_DFP\1.4.351\gcc\dev\atmega328p"  
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Debug\Makefile(145,1): error: recipe for target 'Display.elf' failed
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Debug\Menus\_main.o(1,1): error: multiple definition of `buffer'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Debug\main.o(1,1): error: first defined here
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Debug\Menus\_main.o(1,1): error: multiple definition of `selectedLine'
		main.o:C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Debug/.././main.cpp:32: first defined here
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Debug\Menus\_main.o(1,1): error: multiple definition of `Clockwise'
		main.o:C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Debug/.././main.cpp:32: first defined here
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Debug\Menus\_main.o(1,1): error: multiple definition of `RotaryPosition'
		main.o:C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Debug/.././main.cpp:32: first defined here
		Menus/_main.o: In function `_main()':
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Menus\_main.cpp(15,1): error: undefined reference to `lcd_gotoxy(unsigned char, unsigned char)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Menus\_main.cpp(16,1): error: undefined reference to `lcd_puts(char const*)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Menus\_main.cpp(17,1): error: undefined reference to `lcd_gotoxy(unsigned char, unsigned char)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Menus\_main.cpp(18,1): error: undefined reference to `lcd_puts(char const*)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Menus\_main.cpp(20,1): error: undefined reference to `lcd_gotoxy(unsigned char, unsigned char)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Menus\_main.cpp(21,1): error: undefined reference to `lcd_puts(char const*)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Menus\_main.cpp(22,1): error: undefined reference to `lcd_putc(char)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Menus\_main.cpp(24,1): error: undefined reference to `lcd_gotoxy(unsigned char, unsigned char)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Menus\_main.cpp(25,1): error: undefined reference to `lcd_puts(char const*)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Menus\_main.cpp(27,1): error: undefined reference to `lcd_gotoxy(unsigned char, unsigned char)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Menus\_main.cpp(28,1): error: undefined reference to `lcd_puts(char const*)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Menus\_main.cpp(29,1): error: undefined reference to `lcd_putc(char)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Menus\_main.cpp(31,1): error: undefined reference to `lcd_gotoxy(unsigned char, unsigned char)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Menus\_main.cpp(32,1): error: undefined reference to `lcd_puts(char const*)'
		main.o: In function `main':
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\main.cpp(37,1): error: undefined reference to `lcd_init()'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\main.cpp(39,1): error: undefined reference to `lcd_command(unsigned char)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\main.cpp(40,1): error: undefined reference to `lcd_putc(char)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\main.cpp(41,1): error: undefined reference to `lcd_putc(char)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\main.cpp(42,1): error: undefined reference to `lcd_putc(char)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\main.cpp(43,1): error: undefined reference to `lcd_putc(char)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\main.cpp(44,1): error: undefined reference to `lcd_putc(char)'
		main.o:C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Debug/.././main.cpp:45: more undefined references to `lcd_putc(char)' follow
		main.o: In function `main':
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\main.cpp(48,1): error: undefined reference to `lcd_goto(unsigned char)'
		main.o: In function `DelayCycles':
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Delay\adelay.h(57,1): error: undefined reference to `DelayCyclesUL(unsigned long)'
		main.o: In function `main':
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\main.cpp(68,1): error: undefined reference to `lcd_gotoxy(unsigned char, unsigned char)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\main.cpp(69,1): error: undefined reference to `lcd_putc(char)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\main.cpp(70,1): error: undefined reference to `lcd_gotoxy(unsigned char, unsigned char)'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\main.cpp(71,1): error: undefined reference to `lcd_putc(char)'
		main.o: In function `DelayCycles':
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Delay\adelay.h(57,1): error: undefined reference to `DelayCyclesUL(unsigned long)'
collect2.exe(0,0): error: ld returned 1 exit status
		make: *** [Display.elf] Error 1
		The command exited with code 2.
	Done executing task "RunCompilerTask" -- FAILED.
Done building target "CoreBuild" in project "Display.cppproj" -- FAILED.
Done building project "Display.cppproj" -- FAILED.

Build FAILED.
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========

 

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Oct 7, 2020 - 04:08 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

As always, you should look at the earliest reported error first - because later errors are likely to be either a direct result, or related.

 

So the first error is a multiple definition:

C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Debug\Menus\_main.o(1,1): error: multiple definition of `buffer'
C:\Users\awn\Antronics\Tech\atmel\AVR\Display\_work\Display\Debug\main.o(1,1): error: first defined here

Note that it tells you where each of the multiple definitions was found: one is in _main.o; the other is in main.o

 

Those are the object files generated by compiling _main.cpp and main.cpp

 

So why do you have two "main" files in your project?

 

 

Surely, that would have given the same errors in the .c version ?

 

Hence why we also need to see the original 'C' version!

 

EDIT

 

the 2 "main" files was not the actual issue - see next post ...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Oct 7, 2020 - 04:36 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Both main.cpp and _main.cpp #include Menus.h:

 

/*
 * Main.h
 *
 * Created: 14/07/1399 07:08:38 PM
 *  Author: AmirSina
 */ 


#ifndef MENUS_H_
#define MENUS_H_

#include <stdlib.h>
#include <stdbool.h>
#include "../Delay/adelay.h"
#include "../LCD/hd44780.h"


volatile uint8_t RotaryPosition;
volatile bool Clockwise;
uint8_t selectedLine;

char buffer[20];

void _main(void);

#endif /* MAIN_H_ */

there you have definitions of RotaryPosition, Clockwise, selectedLine, and buffer.

 

So when you #include that in main.cpp, it will give you definitions of all those things in that compilation unit;

 

And when #include that in _main.cpp, it will also give you definitions of all those things in that compilation unit;

 

So there you have it - multiple definitions of all those things!

 

Your header file should have declarations (not definitions):

/*
 * Menus.h
 *
 * Created: 14/07/1399 07:08:38 PM
 *  Author: AmirSina
 */ 


#ifndef MENUS_H_
#define MENUS_H_

#include <stdlib.h>
#include <stdbool.h>
#include "../Delay/adelay.h"
#include "../LCD/hd44780.h"


extern volatile uint8_t RotaryPosition;
extern volatile bool Clockwise;
extern uint8_t selectedLine;

extern char buffer[20];

void _main(void);

#endif /* MAIN_H_ */

and the definitions should be in a .cpp (or .c)file somewhere.

 

See: http://c-faq.com/decl/decldef.html

and: https://www.avrfreaks.net/forum/tut-modularizing-c-code-managing-large-projects

 

Again, this is all standard C/C++ stuff - nothing specific to AVR, or Atmel Studio

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

In Menus.h

#ifndef MENUS_H_
#define MENUS_H_

#include <stdlib.h>
#include <stdbool.h>
extern "C" {                            //.kbv declare that these are C files 
   #include "../Delay/adelay.h"
   #include "../LCD/hd44780.h"
};                                      //.kbv

extern volatile uint8_t RotaryPosition; //.kbv declare external references
extern volatile bool Clockwise;         //.kbv
extern uint8_t selectedLine;            //.kbv

extern char buffer[20];                 //.kbv

void _main(void);

#endif /* MENUS_H_ */                   //.kbv don't lie in comments

in _main.cpp

#include "Menus.h"

volatile uint8_t RotaryPosition; //.kbv define the actual variables in the .CPP file
volatile bool Clockwise;         //.kbv
uint8_t selectedLine;            //.kbv

char buffer[20];                 //.kbv

uint16_t p0 = 5000;
uint8_t p1 = 100;

void _main(void)
{
	lcd_gotoxy(8, 0);
	lcd_puts("Main");
	lcd_gotoxy(1, 1);
	lcd_puts("Parameter0:");
	itoa(p0, buffer, 10);
	lcd_gotoxy(14, 1);
	lcd_puts(buffer);
	lcd_putc('%');
	
	lcd_gotoxy(1, 2);
	lcd_puts("Parameter1:");
	itoa(p1, buffer, 10);
	lcd_gotoxy(14, 2);
	lcd_puts(buffer);
	lcd_putc('%');
	
	lcd_gotoxy(0, 3);
	lcd_puts("Menu");
}

David.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0


You didn't rename all the .c files to .cpp:

 

 

That'll be why you're getting the "undefined" errors for everything from that file

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

If you’re wanting cpp, start with an Arduino project and use its libraries. I’d expect there would be existing libraries to do what you want and probably even more.....