cancel
Showing results for 
Search instead for 
Did you mean: 

stm32 c++ Linker error

juliuscaesar
Associate III
Posted on March 14, 2018 at 22:47

hey guys

I have an stm32f4 discovery board and used stm32 cube to generate a SW4STM32 project with freertos.

SW4STM32 is able to convert a c project to c++ project.

I have read about the problem when mixing c and c++ code and i know about the mangling of the c++ compiler.

There are lots of extern C header guards in the header files.

However i'm still getting a linker error

Building target: Cpp_Test.elf

Invoking: MCU G++ Linker

arm-none-eabi-g++ -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -specs=nosys.specs -specs=nano.specs -T'../STM32F429ZITx_FLASH.ld' -Wl,-Map=output.map -Wl,--gc-sections -fno-exceptions -fno-rtti -o 'Cpp_Test.elf' @'objects.list'   -lm

Src/freertos.o: In function `StartDefaultTask':

xxxx\Cpp_Test\Debug/../Src/freertos.c:131: undefined reference to `calc_values'

collect2.exe: error: ld returned 1 exit status

makefile:59: recipe for target 'Cpp_Test.elf' failed

make: *** [Cpp_Test.elf] Error 1

my test_cpp.h file looks like this

#ifndef USER_TEST_CPLUS_H_

#define USER_TEST_CPLUS_H_

#include 'stdint.h'

int calc_values();

#endif /* USER_TEST_CPLUS_H_ */

my test_cpp.cpp file looks like this

#include 'test_cplus.h'

#include <iostream>

using namespace std;

class Rectangle {

    int width, height;

  public:

    void set_values (int,int);

    int area() {return width*height;}

};

void Rectangle::set_values (int x, int y) {

  width = x;

  height = y;

}

int calc_values()

{

    Rectangle rect;

    rect.set_values(1,2);

    int area = rect.area();

    return area;

}

the calc_values() function is called from the freertos default task in freertos.c

/* Includes ------------------------------------------------------------------*/

#include 'FreeRTOS.h'

#include 'task.h'

#include 'cmsis_os.h'

/* USER CODE BEGIN Includes */     

#include 'test_file.h'

#include 'test_cplus.h'

/* USER CODE END Includes */

/* Variables -----------------------------------------------------------------*/

osThreadId defaultTaskHandle;

/* USER CODE BEGIN Variables */

/* USER CODE END Variables */

/* Function prototypes -------------------------------------------------------*/

void StartDefaultTask(void const * argument);

extern void MX_USB_DEVICE_Init(void);

extern void MX_FATFS_Init(void);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/* USER CODE BEGIN FunctionPrototypes */

/* USER CODE END FunctionPrototypes */

/* Hook prototypes */

/* Init FreeRTOS */

void MX_FREERTOS_Init(void) {

  /* USER CODE BEGIN Init */

       

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */

  /* add mutexes, ... */

  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */

  /* add semaphores, ... */

  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */

  /* start timers, add new ones, ... */

  /* USER CODE END RTOS_TIMERS */

  /* Create the thread(s) */

  /* definition and creation of defaultTask */

  osThreadDef(defaultTask, StartDefaultTask, osPriorityNormal, 0, 128);

  defaultTaskHandle = osThreadCreate(osThread(defaultTask), NULL);

  /* USER CODE BEGIN RTOS_THREADS */

  /* add threads, ... */

  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_QUEUES */

  /* add queues, ... */

  /* USER CODE END RTOS_QUEUES */

}

/* StartDefaultTask function */

void StartDefaultTask(void const * argument)

{

  /* init code for USB_DEVICE */

  MX_USB_DEVICE_Init();

  /* init code for FATFS */

  MX_FATFS_Init();

  /* USER CODE BEGIN StartDefaultTask */

  /* Infinite loop */

  for(;;)

  {

      run_test();

      calc_values(); //=> this causes the linker error

    osDelay(100);

  }

  /* USER CODE END StartDefaultTask */

}

/* USER CODE BEGIN Application */

/* USER CODE END Application */

could you give me a hint why this is not working?

1 ACCEPTED SOLUTION

Accepted Solutions
Pavel A.
Evangelist III
Posted on March 14, 2018 at 23:14

There are lots of extern C header guards in the header files.

But none in the code you've posted. So go add the 

extern 'C' guards  around your C++ functions exported to C.

- pa

View solution in original post

4 REPLIES 4
Pavel A.
Evangelist III
Posted on March 14, 2018 at 23:14

There are lots of extern C header guards in the header files.

But none in the code you've posted. So go add the 

extern 'C' guards  around your C++ functions exported to C.

- pa

Andrew Neil
Evangelist
Posted on March 14, 2018 at 23:19

Hopefully this is just a typo in your post; you say:

my

test_cpp.h

file looks like this

But everywhere that #includes it calls it 

'test_cplus.h'

Posted on March 14, 2018 at 23:35

Name mangling?

extern 'C' int calc_values()

{

    Rectangle rect;

    rect.set_values(1,2);

    int area = rect.area();

    return area;

}

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
juliuscaesar
Associate III
Posted on March 14, 2018 at 23:39

@andrew this was a typo

🙂

^^

@pavel That did work.

I thought i only needed the extern c guards when implementing c code in c++ functions, not the other way around.

@clive: according the wikipedia the c++ compiler uses the function name and the arguments the generate unique names. The C compiler only uses the names. Thats why overloading is only possible in C++.

And this process is called name mangling. (at least that's what i understood, feel free to correct me if i'm wrong )

Thx for your quick help guys