ColdPixel
ColdPixel

Reputation: 13

How to fix C++ "Undefined reference to ..." C function pointer?

I am trying to call a function (from an #included library) that takes as a parameter a function pointer, and passing to this function a pointer to a function located in a C file. The compiler throws an "undefined reference to [function name]" error.

I tried removing the code from the .c file and putting it directly into main.cpp file (see below the section marked 'THIS WORKS') - and the error is avoided. I know that I should be able to keep it in the .c file because I am following very closely to an example that compiles without errors.

/****************/
/*** MAIN.CPP ***/
/****************/

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

using namespace touchgfx;

/* Kernel includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

#define configGUI_TASK_PRIORITY                 ( tskIDLE_PRIORITY + 3 )
#define configGUI_TASK_STK_SIZE                 ( 1024 )

static void GUITask(void* params)
{
    /* STUFF */
}


/*********** THIS WORKS ************/

/*
void btn_tasked(void* params)/{
    /* STUFF */
}
*/

/*********** THIS WORKS ************/


int main(void)
{
    xTaskCreate(GUITask, "GUITask",
                configGUI_TASK_STK_SIZE,
                NULL,
                configGUI_TASK_PRIORITY,
                NULL);

    /* error undefined reference to btn_task */
    xTaskCreate(btn_task, "BTNTask",
               512,
               NULL,
               configGUI_TASK_PRIORITY+1,
               NULL);

    for (;;);
}

This is btntask.h

/****************/
/*** btntask.h ***/
/****************/
#ifndef BTNTASK_H
#define BTNTASK_H

    void btn_task(void* params);

#endif /* BTNTASK_H */

This is btntask.c

/****************/
/*** btntask.c ***/
/****************/

#include "btntask.h"

void btn_task(void* params)
{
  /* STUFF */
}

The compiler log is as follows:

Converting images
Compiling Core/Src/main.cpp
Linking TouchGFX/build/bin/target.elf
TouchGFX/build/ST/STM32F429IDISCO/Core/Src/main.o: In function `main':
d:\Dropbox\TouchGFXProjects\MiniGame\Project/Core/Src/main.cpp:116: undefined reference to `btn_task'
collect2.exe: error: ld returned 1 exit status
gcc/Makefile:363: recipe for target 'TouchGFX/build/bin/target.elf' failed
make[2]: *** [TouchGFX/build/bin/target.elf] Error 1
gcc/Makefile:359: recipe for target 'generate_assets' failed
make[1]: *** [generate_assets] Error 2
../gcc/Makefile:45: recipe for target 'all' failed
make: *** [all] Error 2

The compilation is performed by the software package I am using (TouchGFX). If it is helpful, this is the compilation commands reported in the log:

touchgfx update_project --project-file=simulator/msvs/Application.vcxproj && touchgfx update_project --project-file=../EWARM/application.ewp && touchgfx update_project --project-file=../EWARM6/project.ewp && touchgfx update_project --project-file=../MDK-ARM/application.uvproj

make -f ../gcc/Makefile -j8

* UPDATE * I noticed that TouchGFX populates a Debug folder of .obj files, one for each of the source code files in the application, and I can see that it is missing a btntask.obj. Clearly it is not linking the btntask.obj file. I need to figure out why that is. There is a makefile that details all of the linking, but it uses a lot of syntax I am not familiar with.

* SOLUTION * Turns out that the Makefile names a list of directories to include. The solution was to edit the list to add additional directories where my btntask files are located.

# Directories containing application-specific source and header files.
# Additional components can be added to this list. make will look for
# source files recursively in comp_name/src and setup an include directive
# for comp_name/include.
components := TouchGFX/gui target TouchGFX/generated/gui_generated

Thanks everyone for chiming in.

Upvotes: -1

Views: 2792

Answers (1)

jiandingzhe
jiandingzhe

Reputation: 2121

You need to be aware these two concepts:

Name Mangling

You may need to wrap btn_task inside extern "C" in your btntask.c file, as well as in your header file.

As your project contains C++ file, your C file might be compiled by C++ compiler, not C compiler. Then your C function implementation is name-mangled. But the referring position is still using the non-mangled name.

Link

Don't forget to include product of btntask.c in link stage.

After all, I'm not familiar with your project controlling software, you have to ensure those two points by yourself.

Upvotes: 1

Related Questions