2018-03-14 02:47 PM
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++ Linkerarm-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' -lmSrc/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 statusmakefile:59: recipe for target 'Cpp_Test.elf' failedmake: *** [Cpp_Test.elf] Error 1my 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?
Solved! Go to Solution.
2018-03-14 03:14 PM
>
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
2018-03-14 03:14 PM
>
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
2018-03-14 03:19 PM
Hopefully this is just a typo in your post; you say:
my
test_cpp.hfile looks like thisBut everywhere that #includes it calls it
'test_cplus.h'
2018-03-14 03:35 PM
Name mangling?
extern 'C' int calc_values()
{
Rectangle rect;
rect.set_values(1,2);
int area = rect.area();
return area;
}
2018-03-14 03:39 PM
@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