编译自定义FFmpeg C++滤镜时遇未定义引用错误求助
你这是踩了C/C混合编译的经典坑——**名字修饰(name mangling)**导致链接器找不到C函数的符号。我来一步步帮你搞定:
核心问题分析
你用C实现的MyFunction,会被C编译器做特殊的名字修饰(比如把MyFunction变成_Z11MyFunctionv这种格式),但FFmpeg的滤镜接口是C语言的,你的vf_foobar.c里调用的是未修饰的C风格符号,链接器找不到匹配的符号,就报了undefined reference错误。
分步解决方案
1. 给C++接口加上extern "C"包裹
修改你的MyCode.h,把要在C代码里调用的函数声明用extern "C"包裹,强制C++编译器按照C的规则生成符号:
#ifdef __cplusplus extern "C" { #endif // 这里放你要在C代码里调用的函数声明 void MyFunction(); #ifdef __cplusplus } #endif
这样MyFunction的符号就会和C代码里调用的一致,不会被C++修饰。
2. 告诉Makefile用C++编译器编译你的.cpp文件
在libavfilter/Makefile里,除了已添加的OBJS-$(CONFIG_FOOBAR_FILTER) += vf_foobar.o MyCode.o,还要添加编译规则,指定MyCode.cpp用C++编译器编译:
MyCode.o: MyCode.cpp $(CXX) $(CFLAGS) $(CXXFLAGS) -c -o $@ $<
FFmpeg的构建系统里$(CXX)就是预设的C编译器,$(CXXFLAGS)包含了C编译需要的参数。
3. 链接时引入C++标准库
C++代码依赖标准库,你需要让链接器自动链接它。在libavfilter/Makefile里添加:
LIBS-$(CONFIG_FOOBAR_FILTER) += -lstdc++
这样编译滤镜模块时,会自动带上-lstdc++参数,避免后续出现标准库函数的未定义引用。
4. 重新编译
先清理之前的编译产物,避免残留问题:
make clean
然后重新执行编译命令:
make -j$(nproc) ffmpeg
(如果之前配置FFmpeg时没开启你的滤镜,记得先运行./configure --enable-filter=foobar之类的命令开启)
验证小技巧
编译成功后,你可以用这个命令查看符号是否正确:
nm -D libavfilter/libavfilter.a | grep MyFunction
如果能看到未被修饰的MyFunction符号,就说明问题彻底解决了。
内容的提问来源于stack exchange,提问作者lfk

