Troubles with multiples files (and structures typedef too)

Hi folks,
I'm experienced with C and C++ programming, but I can't figure out what I'm doing wrong here. I want to have multiple files in my project, the main file containing setup() and loop(), one other file with functions, one other with structures, etc...
When I put everything in the main file, it compiles just fine, which is not the cas with separate files. Here is my code :

final.ino

void setup()
{
  initSensors();
}

void loop()
{
  getDataSensors();
}

sensors.ino

void initSensors()
{
}

struct sensorData getDataSensors()
{
  struct sensorData data;
  data.gyroX = 200;
  data.gyroY = 130;
  data.gyroZ = -75;
  data.accX = -500;
  data.accY = 45;
  data.accZ = 112;
  return data;
}

structures.ino

typedef struct sensorData
{
  int gyroX;
  int gyroY;
  int gyroZ;
  int accX;
  int accY;
  int accZ;
};

The code actually does nothing, it's just for the purpose of testing. I'm using arduino software 1.0. The mistakes I get :

final.cpp: In function 'void loop()':
final:15: error: invalid use of incomplete type 'struct sensorData'
final:-1: error: forward declaration of 'struct sensorData'
final.cpp: In function 'sensorData getDataSensors()':
sensors:10: error: return type 'struct sensorData' is incomplete
sensors:10: error: new declaration 'void getDataSensors()'
final:-1: error: ambiguates old declaration 'sensorData getDataSensors()'
sensors:12: error: aggregate 'sensorData data' has incomplete type and cannot be defined

Am I missing something here ?

Also, one thing I've noticed, if I write a structure and use a typedef, the typedef doesn't seems to be taken in account. I've tried both syntax :

typedef struct foo foo;
struct foo
{
//...
};
typedef struct foo
{
//...
}foo;

None of the typedef works, I always have to write "struct foo" instead of "foo" if I want the program to compile.

Any help would be greatly appreciated :wink:

A typedef takes two parts - the type to be aliased and the alias.

typedef struct foo foo;

Typically, you want to use a different name for the alias and the structure. Try

typedef struct foo Foo;
typedef struct foo
{
//...
}foo;

Same issue here.

struct sensorData getDataSensors()
{
  struct sensorData data;
  data.gyroX = 200;
  data.gyroY = 130;
  data.gyroZ = -75;
  data.accX = -500;
  data.accY = 45;
  data.accZ = 112;
  return data;
}

data is a local variable. Returning data this way requires making a copy of the struct, and returning that copy.

You should learn about pointers or references (or both). Pass the function a reference (or pointer) to a struct that it is to store data in. Create that struct before calling the function.

final.cpp: In function 'void loop()':
final:15: error: invalid use of incomplete type 'struct sensorData'
final:-1: error: forward declaration of 'struct sensorData'

When you have a bunch of ino (or pde) files, you have no control over the order that the files are combined in. What is happening here is that the type of an object is known, and used, before the type is defined.

Put the structure definition in a .h file, rather than a .ino (or .pde) file, and #include the .h file where needed. This puts the definition before any uses.

The .h solution is perfect, thanks ! I can also bring some answers to my other problems :

Typically, you want to use a different name for the alias and the structure.

I've tested it, and you don't need to, just like in C :wink:

data is a local variable. Returning data this way requires making a copy of the struct, and returning that copy.

You should learn about pointers or references (or both). Pass the function a reference (or pointer) to a struct that it is to store data in. Create that struct before calling the function.

Actually there is no need for pointers or references here, the copy of data is automatically made by the "return". Your method might be better to reduce dynamic memory consumption, but I suppose the gain in terms of speed must be quite low...

Your method might be better to reduce dynamic memory consumption, but I suppose the gain in terms of speed must be quite low...

True. But memory is the thing that is most constrained on an Arduino.

I've tested it, and you don't need to, just like in C

Need and want are different things. I look at your code and see foo, and struct foo, and wonder why? I see Foo and struct foo, and I see that they are different things. YMMV.

True. But memory is the thing that is most constrained on an Arduino.

I agree, but your code provides a gain in dynamic memory of the size of the structure during a very limited time (the time the copy is made), I don't think we can call that a gain in memory (the memory allocated for the copy is immediatly deallocated or sent back to a memory pool, anycase it's available immediatly). Especially since it's not like you have a thousand returned variables at the same time, it's only one that is copied. The real gain is in term of speed, you can gain some time by avoiding doing the copy.

Need and want are different things. I look at your code and see foo, and struct foo, and wonder why? I see Foo and struct foo, and I see that they are different things. YMMV.

Well, I respect that, but the meaning of that instruction :

typedef struct foo foo;

is : "replace" "struct foo" by "foo
and in that case it makes perfect sense.

Well, I respect that, but the meaning of that instruction :

typedef struct foo foo;

is : "replace" "struct foo" by "foo
and in that case it makes perfect sense.

I'm not sure what the benefit is of hiding the fact that foo is a struct, which is all that your typedef is doing. Using a typedef to give a different name to "struct foo" has some benefits, but just hiding the fact that foo is a struct doesn't seem that useful.