Rik's Ramblings

Wednesday, January 04, 2012

Troubles with typedef on the Arduino

Why doesn't this work on the Arduino!?

typedef struct {
   int a;
   int b;
} TTallywag;


void DillyDally(TTallywag *tw){
// stuff...
}

In short, I don't actually know! But I know how to get around it!

To make it work, you have to change how you use your new data type - infact, your function parameters can't use types that you've typedef'ed, but you can use the type if you do so thusly:

typedef struct _tallywag {
   int a;
   int b;
} TTallywag;


void DillyDally(struct _tallywag *tw){
   // stuff...
}


According to the following page that I found, you should be able to use the TTallywag if you define it in a header file and including that into you sketch.


Note to self: Google 'Using headers in Arduino sketches'

I suppose technically defining types in header files is the right thing to do, but when you're dealing with a sketch that's only short, it seems such an overkill.

Now, the following does works fine. You can use the types inside functions no problemo. Which is partly why I spent so much time tearing out my hair last night!

typedef struct _tallywag{
   int a;
   int b;
} TTallywag;


void *ShillyShally(int alpha, int beta){
   static TTallywag tw;

   // stuff...


   tw.a = alpha;
   tw.b = beta;

   return &tw;
}

Must be some namespacing, or name mangling going on.

So it's not a huge problem, but if you're planning to share code modules between two devices, say one half in Linux written using GCC and the other half Arduino: Define your functions the latter way! That will work on both sides.

2 Comments:

  • Believe it or not, the Arduino pipeline is just being stupid...

    What happens is the following:
    your sketch:
    [code]
    typedef struct {
    int a;
    int b;
    } TTallywag;


    void DillyDally(TTallywag *tw){
    // stuff...
    }

    void setup(){}
    void loop(){}
    [/code]


    Will be thrown through a little tool that's in the Arduino build pipeline. One of the things it does is add an include for "WProgram.h" so you can use all the Arduino functions. The resulting file (a normal .cpp file, located in some temporary folder) is then passed to avr-gcc for actual compilation. Now this is where shit hits the fan...

    Your program will actually look like this:

    [code]
    #include "WProgram.h"
    void DillyDally(TTallywag *tw);
    void setup();
    void loop();
    typedef struct {
    int a;
    int b;
    } TTallywag;


    void DillyDally(TTallywag *tw){
    // stuff...
    }

    void setup(){}
    void loop(){}
    [/code]

    Notice how they threw a couple of function declarations at the top of the file, before the typedef. Now there's your compile error.

    They probably did this so new programmers, unfamiliar with C/C++, wouldn't have to declare their functions before using them.

    The reason why putting the typedef in a header file works is because includes are placed above function declarations. So by the time the compiler sees the function declaration it already has handled the typedef.

    By Anonymous Anonymous, at 2/14/12, 9:23 AM  

  • Yes, this page gives a good overview of that process:
    http://arduino.cc/en/Hacking/BuildProcess

    Specifically:

    "... the environment searches for function definitions within your main sketch file and creates declarations (prototypes) for them. These are inserted after any comments or pre-processor statements (#includes or #defines), but before any other statements (including type declarations). This means that if you want to use a custom type as a function argument, you should declare it within a separate header file."

    By Blogger UK Dive Boy, at 2/14/12, 9:51 AM  

Post a Comment



<< Home