multiple definitions of class instances

(I can't delete this post...) but you can ignore it if you like since, as you can see from the next post, I fixed it.



I have tried for several hours to figure this out... over six now... and getting nowhere. At link time I get this...

1
2
3
4
5
6
7
8
c:/users/peted/.platformio/packages/toolchain-xtensa-esp32s3/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld.exe: .pio\build\um_feathers3\src\pulseCount.cpp.o:C:\Users\peted\OneDrive\Documents\PlatformIO\Swarm\Tzatziki/src/mysensors.h:106: multiple definition of `PulseSensor2'; .pio\build\um_feathers3\src\initialize.cpp.o:C:\Users\peted\OneDrive\Documents\PlatformIO\Swarm\Tzatziki/src/mysensors.h:106: first defined here

c:/users/peted/.platformio/packages/toolchain-xtensa-esp32s3/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld.exe: .pio\build\um_feathers3\src\pulseCount.cpp.o:C:\Users\peted\OneDrive\Documents\PlatformIO\Swarm\Tzatziki/src/mysensors.h:102: multiple definition of `PulseSensor1'; .pio\build\um_feathers3\src\initialize.cpp.o:C:\Users\peted\OneDrive\Documents\PlatformIO\Swarm\Tzatziki/src/mysensors.h:102: first defined here

c:/users/peted/.platformio/packages/toolchain-xtensa-esp32s3/bin/../lib/gcc/xtensa-esp32s3-elf/8.4.0/../../../../xtensa-esp32s3-elf/bin/ld.exe: .pio\build\um_feathers3\src\pulseCount.cpp.o:C:\Users\peted\OneDrive\Documents\PlatformIO\Swarm\Tzatziki/src/mysensors.h:110: multiple definition of `AnalogSensor1'; .pio\build\um_feathers3\src\initialize.cpp.o:C:\Users\peted\OneDrive\Documents\PlatformIO\Swarm\Tzatziki/src/mysensors.h:110: first defined here

collect2.exe: error: ld returned 1 exit status
*** [.pio\build\um_feathers3\firmware.elf] Error 1 


It seems like mysensors.h is being run through more than once.
I of course have guards on mysensors.h

1
2
3
4
#ifndef _MYSENSORS_H_
#define _MYSENSORS_H_
//..
#endif  


mysensors.h has all of my classes defined for the my sensors and at the end of the file, I invoke some instances of them:

1
2
3
4
5
PulseSensor PulseSensor1(PIN_IN_PULSE_1, IN_PULSE_1_SAMPLE_FREQUENCY, IN_PULSE_1_REPORTS_PER_DAY, IN_PULSE_1_MATH);

PulseSensor PulseSensor2(PIN_IN_PULSE_2, IN_PULSE_2_SAMPLE_FREQUENCY, IN_PULSE_2_REPORTS_PER_DAY, IN_PULSE_2_MATH);

AnalogSensor<2048> AnalogSensor1(PIN_IN_ANALOG_1, IN_ANALOG_1_SAMPLE_FREQUENCY, IN_ANALOG_1_REPORTS_PER_DAY, IN_ANALOG_1_MATH);


This is a structure that I have used in multiple other programs without issue but clearly am doing something wrong here.

I have fiddled with eliminating as many #includes in my program as I can to see if they are conflicting, but no joy there.

Any suggestions are welcome. Thank you.
Last edited on
Is that last excerpt in one of your header files? You are going to have multiple definitions of PulseSensor1, PulseSensor2, and AnalogSensor1 if you #include that header into multiple, separate .cpp files.

If you need global variables like that, you declare it as extern in the header, and define it in exactly one compilation unit (one .cpp flie).
Last edited on
Well, another half hours and I nailed it... seems like I had already eliminated other #include mysensor.h statements, but I missed one and I moved two of the constructions to another file. So frustrating...
Ganado,
Thank you. So... as I move along here, and I want to use, in multiple places in my code, my class methods defined in mysensor.h which are tied to creation of the object such as PulseSensor1 and AnalogSensor1 (shown above), (such as AnalogSensor1.ClearData(), how can I keep them accessible in multiple places in my code without #includes in the .cpp files that need to access them? I have tried putting the creation of the objects in other places in the code, and that causes other problems. How can I treat the objects like functions (that are made globally available by listing them in a header file, so I end up with them more globally available?
Thanks!
Search the web for "extern global variable".
https://stackoverflow.com/questions/1433204/how-do-i-use-extern-to-share-variables-between-source-files

Look at the first example that has file3.h, file1.c, and file2.c.
The example uses a global int variable, but the same pattern applies to any type/class.

AnalogSensor.hpp
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
#ifndef MYSENSORS_HPP_
#define MYSENSORS_HPP_

#include <iostream>

template <int Bits>
class AnalogSensor
{
  public:
	void ClearData()
	{
		std::cout << "Clearing " << Bits << " bits...\n";
	}
	
	void SomethingElse()
	{
		std::cout << "Something else...\n";
	}
};

extern AnalogSensor<2048> AnalogSensor1;

void use_AnalogSensor1();

#endif   


AnalogSensor.cpp
1
2
3
4
5
6
7
8
9
#include "AnalogSensor.hpp"

// Defined in exactly one .cpp file; not in a header
AnalogSensor<2048> AnalogSensor1;

void use_AnalogSensor1()
{
	AnalogSensor1.ClearData();
}


main.cpp
1
2
3
4
5
6
7
8

#include "AnalogSensor.hpp"

int main()
{
	use_AnalogSensor1();
	AnalogSensor1.SomethingElse();
}

Thank you Ganado. I of course have used extern for variables but had no idea that it could be used for a class (my mind tends to think of classes as a bunch of functions (methods) rather than a bunch of data).

That might be the "big breakthrough" I needed.

Again, many thanks!
Brilliant Ganado! That solved a lot for me!
Thanks!
Topic archived. No new replies allowed.