0

I am having a similar problem to the one described in this post:

Why isn't my SysTick_Handler() being called in my LPCxpresso C++ Project?

I have a couple of .cpp files, but the rest are .c files. Everything builds just file except when I try to reference a stand-alone function in a .cpp file from a .c file. Even though I have the entire function in the .cpp file enclosed in:

extern "C" {
    void function( void ) {
       .
       .
       .
    }
}

I still get an undefined reference to 'function' in the calling .c file. Any ideas? It really has me stumped and I'm trying to add some elegance to some very procedural code by using class objects that make total sense in this application.

Gonzo
  • 9
  • 1
  • 1
    Do you get the error message when compiling the calling *.c file or when linking the entire project? Did you forward-declare the C function in the calling *.c file or in an included *.h file? –  Jun 26 '14 at 18:17
  • Thanks for the quick reply fmunkert. The error is from the Linker. I have tried placing: extern "C" function(); in both the .h and the calling .c file itself. That call generates an error indicating that it does not like the literal string (the "C"). – Gonzo Jun 26 '14 at 21:55
  • And forward declaring the function as simply: void function(); still generates the undefined error from the linker (of course as the actual function name is probably mangled). – Gonzo Jun 26 '14 at 21:59

1 Answers1

1

The C++ function needs to be declared as extern "C" when compiled by C++, but not when compiled in C (because the C language assumes all functions use C calling convention).

In the header file that declares foo(), use the __cplusplus predefined macro to enclose the opening and closing brace of the extern "C" declaration.

This header should be #include-ed in both the C and C++ code, but the extern "C" declaration will only be active for the C++ compiler.

// near start of the header file...
#ifdef __cplusplus
extern "C" {
#endif

// declaration of function foo
void foo(void);

// ...at the end of the header file
#ifdef __cplusplus
}; // this brace closes the extern "C" declaration
#endif

When you define the implementation, the function has to be declared extern "C":

// foo.cpp
extern "C" void foo(void)
{
    // implementation of function foo
}

In C++ it's legal to have both int foo(int) and int foo(double) as long as both functions have the same return type. The function names get "name-mangled" to distinguish the different argument lists (for example i32fooi32 and i32fooD80). These mangled names are visible at the linker level, and different C++ compilers use different name-mangling schemes. The key for linking with C is to avoid name-mangling altogether. This is why both the declaration and the definition have to be marked extern "C".

MarkU
  • 14,413
  • 1
  • 34
  • 53
  • Thanks MarkU. I tried variations on this before, but this solved it for me! – Gonzo Jun 27 '14 at 04:47
  • Great, glad to help. If this was useful can you mark this answer as accepted? – MarkU Jun 27 '14 at 06:37
  • MarkU, I spoke too soon. :( When I made the change last night, I forgot to put the actual call to function() back into the .c file where I had left it commented out during previous attempts to make it work. Unfortunately, even using your suggestion, I still get the undefined reference error. I will try to include the actual output from the Linker as soon as I figure out how. – Gonzo Jun 27 '14 at 15:18
  • In two parts: arm-none-eabi-gcc -nostdlib -L"/Users/edwardrotberg/Documents/LPCXpresso_7.2.0/workspace/LPC11xx_Lib/Release" -L"/Users/edwardrotberg/Documents/LPCXpresso_7.2.0/workspace/CMSISv1p30_LPC11xx/Release" -Xlinker -Map=Proto11.map -Xlinker --gc-sections -mcpu=cortex-m0 -mthumb -T "Proto11_31k.ld" -o"Proto11.axf" ./src/cr_startup_lpc11.o ./src/effects.o ./src/flash.o ./src/gpio.o ./src/main.o ./src/ssp.o ./src/timer16.o ./src/uart.o -lCMSISv1p30_LPC11xx ./src/main.o: In function `main': – Gonzo Jun 27 '14 at 15:21
  • /Users/edwardrotberg/Documents/LPCXpresso_7.2.0/workspace/Proto11/Release/../src/main.c:136: undefined reference to `effectBurningBike' collect2: error: ld returned 1 exit status make: *** [Proto11.axf] Error 1 – Gonzo Jun 27 '14 at 15:21
  • Maybe first try a trivial proof-of-concept program, with `extern "C" foo()` declared in foo.h, implemented in foo.cpp, and called from `main()` in testfoo.c. So only a C main() function calling a C++ function. Suggest also check map file. Without the `extern "C"`, C++ will decorate the function name e.g. `qxyeffectBurningBikedd3s` instead of `effectBurningBike` or `_effectBurningBike` as C would expect for an extern function name. – MarkU Jun 28 '14 at 03:07
  • Also have to use extern "C" in the definition as well as the declaration. Will edit my answer to reflect this point... – MarkU Jun 28 '14 at 03:17