【问题标题】:How to fix C++ "Undefined reference to ..." C function pointer?如何修复 C++“未定义的引用 ...”C 函数指针?
【发布时间】:2019-01-04 01:20:20
【问题描述】:

我正在尝试调用一个函数(来自#included 库),该函数将函数指针作为参数,并将指向位于 C 文件中的函数的指针传递给该函数。编译器会抛出“未定义的对 [函数名称] 的引用”错误。

我尝试从 .c 文件中删除代码并将其直接放入 main.cpp 文件(请参阅下面标记为“此工作”的部分) - 并且避免了错误。我知道我应该能够将它保存在 .c 文件中,因为我非常关注一个编译没有错误的示例。

/****************/
/*** 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 (;;);
}

这是 btntask.h

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

    void btn_task(void* params);

#endif /* BTNTASK_H */

这是 btntask.c

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

#include "btntask.h"

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

编译日志如下:

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

编译是由我正在使用的软件包(TouchGFX)执行的。如果有帮助,这是日志中报告的编译命令:

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

* 更新 * 我注意到 TouchGFX 填充了一个 .obj 文件的 Debug 文件夹,应用程序中的每个源代码文件都有一个,我可以看到它缺少 btntask.obj。显然它没有链接 btntask.obj 文件。我需要弄清楚为什么会这样。有一个详细说明所有链接的生成文件,但它使用了很多我不熟悉的语法。

* 解决方案 * 结果是 Makefile 命名了要包含的目录列表。解决方案是编辑列表以添加我的 btntask 文件所在的其他目录。

# 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

感谢大家的参与。

【问题讨论】:

  • 你知道extern "C"是做什么的吗?
  • extern "C" 看起来不错,实际上,如果有点陈旧(通常只在 C++存在之前的 C 头文件中看到)。从输出看,btntask.c 文件似乎没有被编译或链接。
  • 显示编译命令
  • 很难破译发布的代码,因为它在一个屏幕上相当于一个编辑窗口。什么编译在哪里?你在一个模块中有一个extern "C",然后你没有btntask.c ——但是这是编译为C++ 还是C 模块? (我不知道您使用的编译器如何或是否将文件作为 C 文件或 C++ 文件处理)。也许你应该分解你的编辑,并准确说明你作为一次工作编译的内容,然后是你为第二次工作编译的内容。
  • TouchGFX 知道 btntask.c 存在吗?看起来它没有尝试编译或链接它。如果您不使用 IDE 创建文件,某些 IDE 会很生气。

标签: c++ c


【解决方案1】:

您需要了解这两个概念:

名称修改

您可能需要在 btntask.c 文件以及头文件中将 btn_task 包装在 extern "C" 中。

由于您的项目包含 C++ 文件,您的 C 文件可能由 C++ 编译器编译,而不是 C 编译器。然后你的 C 函数实现是名称混乱的。但是引用位置仍然使用未损坏的名称。

链接

不要忘记在链接阶段包含btntask.c 的产品。

毕竟我对你的项目控制软件不熟悉,这两点你自己搞定。

【讨论】:

    猜你喜欢
    • 2018-05-21
    • 1970-01-01
    • 2012-09-17
    • 1970-01-01
    • 1970-01-01
    • 2016-05-12
    • 2011-07-26
    • 2021-11-14
    • 1970-01-01
    相关资源
    最近更新 更多