Duplicate declaration confusion

I have an .ino file with variables that are declared in a src\ .h file. I also have src\ .cpp files that use those variables.

If I #include the .h file in the .ino file, that works for the .ino file but not the src\ .cpp files. (not declared in this scope)

If I #include the .h file in the src\ .cpp files but not the .ino file, it works for the src\ .cpp files but not the .ino file. (not declared in this scope)

If I #include the .h file in both the .ino file and the src\ .cpp files I get a duplicate declaration error.

How do I make this work?

Use "extern" on the declarations in the .h file and then define the variables in one of the .cpp files. The "extern" tells the compiler that the linker will know where they are so it doesn't need to see the actual definition.

thanks John, I almost understand that. Disclaimer, I just began trying to create an Arduino program.

This is the actual error that I get with the include in both the .ino and .cpp files
sketch\src\u2A_u2A.cpp.o (symbol from plugin): In function u2A_u2A()': (.text+0x0): multiple definition of u2Aleft'

My declaration in the .h file is this form
struct u3Cleft {
int pinnumber;
int state;
const char* function;
}

And they are already defined as part of the struct, right?
u3Cleft[1] =
{
{ 30, 0, "A/B4 VBUS"},
};

the .ino file uses it like this
if(digitalRead(u3Cright[3].pinnumber)==LOW)

& .cpp like this
digitalWrite(u3Cleft[i].pinnumber, LOW);

So would I put "extern" here?
extern struct u3Cleft {

but not redefine them in a .cpp, right? and #include the .h file in both .ino and .cpp?

Put this in the .h file:

struct u3Cleft
{
  int pinnumber;
  int state;
  const char* function;
};
extern  u3Cleft u3Cleft[1];

Put this in one of the .cpp files, somewhere after the #include of the .h file:

u3Cleft u3Cleft[1] =
{
  {30, 0, "A/B4 VBUS"},
};

To keep what sanity I have left, can I create another .cpp file with just

#include "connStruct.h"

u3Cleft u3Cleft[1] =
{
{30, 0, "A/B4 VBUS"},
};

since the .cpp files contain individual sections of the program and I would rather not mix it up.

I have a lot of these, I only included a sample.

Yes, you can put global variable definitions in a separate .cpp file.

I think I have it but now I am getting this error
error: expected primary-expression before '[' token
pinMode(u3Aleft[3].pinnumber, OUTPUT);

for this all the places those variables are used
// Set u3A/2A left GRD low
pinMode(u3Aleft[3].pinnumber, OUTPUT);
digitalWrite(u3Aleft[3].pinnumber, LOW);

The .h file, same as before.

I think I have it but now I am getting this error
error: expected primary-expression before '[' token
pinMode(u3Aleft[3].pinnumber, OUTPUT);

for this all the places those variables are used
// Set u3A/2A left GRD low
pinMode(u3Aleft[3].pinnumber, OUTPUT);
digitalWrite(u3Aleft[3].pinnumber, LOW);

That is the error you would expect if you didn't include the .h file or the .h file didn't have the "extern" declaration for that variable.

I am including the connStruct.h file in both the .ino & .cpp files
the conndef.cpp file also has that include.

This is what is in the .h file for that variable
struct u3Aleft {
int pinnumber;
int state;
const char* function;
};
extern u3Aleft u3Aleft[9];

This is what is in the .cpp file for that variable

u3Aleft u3Aleft[9] =
{
{ 30, 0,"1 Vcc" },
{ 27, 0,"2 D-" },
{ 25, 0,"3 D+" },
{ 31, 0,"4 GND" },
{ 23, 0,"5 SSRX-" },
{ 22, 0,"6 SSRX+" },
{ 32, 0,"7 DRAIN" },
{ 21, 0,"8 SSTX-" },
{ 20, 0,"9 SSTX+" }
};

I don't see the problem. It appears it is as you described.

Hold on, I just got a different error

connectorDefs.cpp:40:1: error: 'u3Aleft' does not name a type
u3Aleft u3Aleft[9] =

It gets confused when you use the same name for the struct and the variable. This in .cpp fixes it:
struct u3Aleft u3Aleft[9] =

For things like that I like the wise words of Dr. Ian Malcom:
"Just because you could doesn't mean that you should " :wink:

John
So I declared "u3Aleft" as a struct type
"struct u3Aleft {"
and "extern"ed the variable
"extern u3Aleft u3Aleft[9];"
But the definition still must include the type
"struct u3Aleft u3Aleft[9] ="

I then did this for another variable "otg"
declaration
"extern int otg;"

definition
"int org = 0;"

So, I don't understand 2 things:

  1. Why I didn't need to declare "otg" as I did the struct b4 the extern
  2. Why I couldn't make otg global by declaring/defining it the .ino file with "int otg = 0;"

YEAH!!!!!! I it compiled.

thank you!!!!!!!!!!!!!!!

wildbill
Hey, I am open to learn something new. What should I have done?

Give the array a different name. The compiler isn't the only one confused by re-using it.

So, which is the array name
"u3Aleft" or u3Aleft[9] ?

If it is the former, then if I change it to "u3Al"
I would have
"struct u3Al {"

"extern u3Al u3Aleft[9]"
in the .h file

Then
"u3Al u3Aleft[9] ="
in the .cpp file
is that right?

I guess so, that compiles. Thanks

The name of the struct type is u3Aleft and the name of the array of nine of those struct types is also u3Aleft. That is causing confusion.

Yes. If you change the type name you would change it in both lines of your .h file and in the .cpp file. Since the names 'u3Al' and 'u3Aleft' now only have one meaning each, you should no longer have to specify that you mean the struct type name when you define the array.

Got it, thanks
I think I figured my question #2.
global only refers to anything in a particular file.
Since I have multiple files in this program, to make a variable GLOBAL to the program I need to put it into those .h & .cpp files like I did for otg
correct?
Actually, it appears I don't need to define them in the .cpp file. I can do that as I use them.