静态C++库链接libavutil出现未定义引用问题求助
解决FFmpeg静态库链接时未定义引用
av_log_set_level的问题 问题描述
在Ubuntu 22.04环境下,使用g++ 9.4.0编译依赖FFmpeg的静态C++库时,出现错误:undefined reference to av_log_set_level(int)`。
相关代码:
#ifdef __cplusplus extern "C" { #endif #include <libavcodec/avcodec.h> #include <libavutil/avutil.h> #ifdef __cplusplus } #endif int some_func() { av_log_set_level(AV_LOG_QUIET); }
CMake配置:
cmake_minimum_required (VERSION 3.23) add_library(MyLib STATIC lib.cpp) target_link_libraries(MyLib -lavformat -lavcodec -lswscale -lavutil) add_executable(MyApp main.cpp) target_link_libraries(MyApp MyLib -lavformat -lavcodec -lswscale -lavutil)
通过nm命令检查符号:
- 静态库
MyLib.a中的未定义符号:nm MyLib.a | grep av_log_set_level U _Z16av_log_set_leveli libavutil.a中的对应符号:nm /usr/lib/x86_64-linux-gnu/libavutil.a | grep av_log_set_level 0000000000000ff0 T av_log_set_level
可以看到,静态库中对av_log_set_level使用了C++名称修饰,导致查找错误的符号,进而引发未定义引用。
解决方法
1. 修正头文件的extern "C"包裹逻辑
多数FFmpeg发行版的头文件已经内置了__cplusplus判断,手动在外层重复包裹extern "C"可能导致编译器错误识别函数链接类型。直接移除手动添加的extern "C"块,直接包含头文件:
#include <libavcodec/avcodec.h> #include <libavutil/avutil.h> int some_func() { av_log_set_level(AV_LOG_QUIET); }
FFmpeg头文件通常自带如下处理:
#ifdef __cplusplus extern "C" { #endif // 函数声明 #ifdef __cplusplus } #endif
重复包裹会干扰编译器对函数链接类型的判断。
2. 调整CMake链接配置
静态库链接顺序至关重要,改用CMake规范方式查找并链接FFmpeg库,避免手动指定-l参数带来的顺序问题:
cmake_minimum_required (VERSION 3.23) # 查找FFmpeg库 find_package(PkgConfig REQUIRED) pkg_check_modules(FFMPEG REQUIRED IMPORTED_TARGET libavformat libavcodec libswscale libavutil ) add_library(MyLib STATIC lib.cpp) # 链接FFmpeg导入目标 target_link_libraries(MyLib PRIVATE PkgConfig::FFMPEG) add_executable(MyApp main.cpp) target_link_libraries(MyApp PRIVATE MyLib)
pkg_check_modules会自动处理库的依赖顺序和链接选项,确保符号查找正确。
3. 验证符号修饰结果
重新编译静态库后,用nm命令检查符号:
nm MyLib.a | grep av_log_set_level U av_log_set_level
若显示未修饰的C符号av_log_set_level,则说明问题已解决,重新链接可执行文件即可。
环境信息
- Ubuntu 22.04
- g++ 9.4.0
- libavutil-dev:amd64 7:4.2.7-0ubuntu0.1
内容的提问来源于stack exchange,提问作者folibis
相关产品推荐
相关产品推荐

