C++调用FFmpeg接口编译链接失败,找不到avformat相关函数怎么解决
问题原因分析
- 核心原因:C编译器的名字修饰(Name Mangling)导致符号不匹配
FFmpeg是纯C语言实现的库,编译生成的库文件中函数符号就是原始的函数名。你使用clang编译C代码时,若FFmpeg头文件没有用extern "C"包裹,C编译器会对FFmpeg的函数名做C++规则的名字修饰(会把参数类型等信息编码到函数名中),最终修饰后的符号和FFmpeg库内的原始C符号不一致,导致链接器找不到对应符号。 - 次要原因:链接参数顺序错误
部分版本的ld链接器对参数顺序敏感,会按照命令行参数的先后顺序加载符号。你当前的编译命令中把依赖库-lavformat放在了源文件main.cpp之前,链接器加载libavformat时还未读取到main.cpp中对FFmpeg函数的引用需求,就不会主动加载libavformat中的符号,也会导致找不到符号。 - 可能原因:架构不匹配
如果你的设备是Apple M系列芯片,Homebrew默认安装的FFmpeg是arm64架构,而你当前编译目标是x86_64架构,也会出现架构不匹配的符号找不到错误。
解决方案
- 修复头文件引用
将代码中FFmpeg相关的头文件引用用extern "C"包裹,告知编译器这部分是C语言接口,不要做名字修饰,修改后的代码片段如下:
#ifdef __STDC_CONSTANT_MACROS #define __STDC_CONSTANT_MACROS #endif #ifndef INT64_C #define INT64_C(c) (c ## LL) #define UINT64_C(c) (c ## ULL) #endif // 用extern "C"包裹FFmpeg头文件 extern "C" { #include <libavutil/imgutils.h> #include <libavutil/samplefmt.h> #include <libavutil/timestamp.h> #include <libavformat/avformat.h> }
- 调整编译命令顺序
把源文件放在依赖库之前,修改后的编译命令如下:
clang++ -I /usr/local/apps/homebrew/Cellar/ffmpeg/4.4_1/include/ -L/usr/local/apps/homebrew/Cellar/ffmpeg/4.4_1/lib main.cpp -lavformat
- 架构匹配处理
如果是Apple Silicon设备,可在编译命令中指定架构为arm64,命令如下:
clang++ -arch arm64 -I /usr/local/apps/homebrew/Cellar/ffmpeg/4.4_1/include/ -L/usr/local/apps/homebrew/Cellar/ffmpeg/4.4_1/lib main.cpp -lavformat
也可以通过lipo -info /usr/local/apps/homebrew/Cellar/ffmpeg/4.4_1/lib/libavformat.dylib命令查看已安装FFmpeg库支持的架构,和编译目标架构保持一致即可。
内容的提问来源于stack exchange,提问作者Turing Zhu
相关产品推荐
相关产品推荐

