1

I'm trying to get a custom robot to work with the Arduino IDE by declaring a new hardware "board" within the IDE. This contains all the mappings and whatnot, but there exists a library that I have access to the source.

Arduino IDE generates a cpp file as follows:

    #line 1 "cbotj.ino"
    #include "Arduino.h"
    void setup();
    void loop();
    #line 1
    void setup()
    {
         LED_open();
    }

    void loop()
    {

    }

I then get the error:

cbotj.cpp.o: In function `setup':
/Applications/cbotj.ino:3: undefined reference to `LED_open()'

Now in Arduino.h for the hardwares core I have

SUBSYS_OPENSTAT LED_open( void );

The function itself is implemented in another .c file within the core hardware functions (such as pinMode) and is completely valid as it works as a compiled library for other IDE's such as Atmel's AVR Studio 4 and 6.

Why am I getting the undefined reference? Headers are included, etc.

The hardware is selected as it works if I were to use things like pinMode on the pin for an LED works fine.

TIA

Demortes
  • 161
  • 11
  • 2
    Have you set the project to use your compiled library, or added the cpp file to your project? – Joachim Isaksson May 24 '13 at 17:03
  • Aye I did. It's automatically set up through the menus hardware component. Selected my board defined in a user boards.txt. – Demortes May 24 '13 at 17:05
  • I also see the file being compiled in verbose mode `/Applications/Arduino.app/Contents/Resources/Java/hardware/tools/avr/bin/avr-ar rcs /var/folders/mj/ldxmpsp90w5bkwclzkt8srx00000gn/T/build6634653328907666647.tmp/core.a /var/folders/mj/ldxmpsp90w5bkwclzkt8srx00000gn/T/build6634653328907666647.tmp/LED_open.c.o` – Demortes May 24 '13 at 17:08
  • You only show the definition from the header, but not the header context. Are there any conditionals around that definition in the header that might prevent it from being visible at compile time? – lurker May 24 '13 at 17:14
  • Only conditionals I see before it are: `#ifndef Arduino_h #define Arduino_h` – Demortes May 24 '13 at 17:18
  • Check for: (a) The routine is defined in C but declared and used in C++ without `extern "C" …`. This results in the definition and the use having different names as viewed by the linker. (b) Linking with the core.a file listed prior to cbotj.cpp.o. Linkers typically extract only modules from libraries that provide definitions for already encountered references, so libraries must be listed after object modules that use them. (c) Use “nm” or equivalent tool to examine the names defined in core.a and referenced in cbotj.cpp.o. Ensure the name of LED_open appears identically in both files. – Eric Postpischil May 24 '13 at 17:39

2 Answers2

3

When linking to functions from a .c file in a C++ project (which seems to be what you have), you need to declare the function as extern "C".

Try changing the header files';

SUBSYS_OPENSTAT LED_open( void );

to

extern "C" {
    SUBSYS_OPENSTAT LED_open( void );
}

EDIT: Seems more than one file is confused about C++, try putting all your C includes inside extern "C" in your cpp file instead;

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

void setup();
void loop();

void setup()
{
     LED_open();
}

void loop()
{

}
Community
  • 1
  • 1
Joachim Isaksson
  • 176,943
  • 25
  • 281
  • 294
  • I've tried that before, got compiler error:`cores/standard/led324v221.h:40: error: previous declaration of 'SUBSYS_OPENSTAT LED_open()' with 'C++' linkage cores/standard/Arduino.h:85: error: conflicts with new declaration with 'C' linkage` – Demortes May 24 '13 at 17:44
  • Found at that line an `extern` prototype.... I assumed this isn't needed, so I commented it out and it seems to have compiled... but now I have to do it to other header files that will experience the same problem. Will comment if this works and accept the answer, otherwise will come back after I'm done if it fails. – Demortes May 24 '13 at 17:47
  • Too late :P Didn't work, now the library has some undefined references due to the commented out externs. Going to undo my changes, turn around and do the include like that... I have a feeling that'd work. – Demortes May 24 '13 at 17:55
0

Adding header files does nothing for you in terms of ensuring that your linker can find function definitions. That is, given a header file, the linker will not be able to hunt down the file with the definition (if it is different) on it's own. (If you forgot header files, you would get compilation errors along the lines of 'undefined symbol' or something.)

So you need to include the .cpp file in your project (the error arises from not having done that). You think you have (from the comments, just saw), but you probably haven't. :) In the comments you show the inclusion of a .c file; is a typo the issue here? Or the signatures of declaration and definition may inadvertently differ.

Edit: I think I've gotten this error as a result of circular header dependencies but I couldn't immediately create an example. It's extremely unlikely in this case anyway.

Matt Phillips
  • 9,465
  • 8
  • 44
  • 75
  • I'm confused by what you're trying to say here. The library is C, not C++. I would rather avoid converting the entire library into a class for C and just use the functions much like pinMode, thus why I am trying to use it as a custom board, rather than a library. Now the C file is compiled into the object file, but upon linking, LED_open() isn't found, but it obviously has the object file to build it into the final hex file for flashing to my MCU. Am I misunderstanding something? – Demortes May 24 '13 at 17:17
  • "The function itself is implemented in another **cpp** file within the core" Now I'm confused too... – Matt Phillips May 24 '13 at 17:20
  • For the external library, I can't use a precompiled static library as Arduino's IDE dynamically generates a CPP and no way to modify the linker options that I've read. – Demortes May 24 '13 at 17:21
  • There's a LED_open function in LED_open.c, which is the compiled with other files to form core.a and that is linked together with the Arduino 'sketch" to form a complete program. – Demortes May 24 '13 at 17:22