Qt CMake项目混编C/C++报undefined reference to function错误
CMake下Qt6 C/C++混编报
undefined reference to 'say_hello'排查方案 按以下优先级逐一排查,覆盖99%的同类场景:
- 头文件 extern "C" 配置错误
不要在引用头文件的cpp文件里手动包裹extern "C"块,必须在Core.h头文件内部内置C兼容防护,否则很容易出现作用域遗漏、宏判断失效导致的符号修饰不匹配问题。C编译文件时会对函数名做名称修饰生成带签名信息的符号(MinGW下say_hello()会被修饰为_Z9say_hellov),但C编译器编译Core.c时生成的是无修饰的C格式符号,两边符号名不匹配就会触发链接错误。
正确的Core.h写法参考:
修改后MainWindow.cpp中直接正常引入头文件即可,无需额外包裹extern "C":#ifndef CORE_H #define CORE_H #ifdef __cplusplus extern "C" { #endif // 所有对外暴露的C函数声明全部放在这个块内 void say_hello(); #ifdef __cplusplus } #endif #endif // CORE_H#include "Core/Core.h" - CMake源文件路径配置错误
检查add_executable中Core/Core.c的相对路径是否和实际目录结构匹配:如果CMakeLists.txt位于项目根目录,Core文件夹与CMakeLists.txt同级,路径写法正确;如果Core文件夹嵌套在src等子目录下,需要补全相对路径(例如src/Core/Core.c)。路径错误会导致Core.c根本不会被加入编译列表,自然找不到对应函数。
验证方式:查看编译日志的源文件编译序列,是否存在Core.c的编译记录,没有记录即为路径错误。 - 函数定义不符合链接要求
打开Core.c检查两点:say_hello函数名是否和头文件声明完全一致,不存在拼写错误(比如大小写写错、多打少打字符)- 函数定义没有加
static修饰,static修饰的函数作用域仅限当前文件,外部无法链接
正确的Core.c参考:
#include "Core.h" void say_hello() { // 核心业务逻辑 } - 构建缓存异常
如果以上配置都确认正确,直接删除整个build构建目录,重新执行CMake配置、全量编译即可,Qt Creator/CMake的增量构建缓存异常也会触发无意义的链接错误。
符号校验方法
如果需要定位具体符号不匹配问题,可以用MinGW自带的nm工具检查目标文件符号表:
- 找到编译生成的Core.c.o目标文件(位于build目录下对应项目的CMakeFiles子目录中),执行
nm Core.c.o | grep say_hello,正常C编译输出为T say_hello - 找到MainWindow.cpp.o目标文件,执行
nm MainWindow.cpp.o | grep say_hello,正常引用输出为U say_hello;如果输出为U _Z9say_hellov,说明extern "C"未生效,还是按C++规则做了符号修饰。
内容的提问来源于stack exchange,提问作者Jakub Sak
相关产品推荐
相关产品推荐

