g ++编译FFMPEG时在Mac上链接错误

时间:2011-01-03 15:43:56

标签: macos g++ ffmpeg linker-errors

Snow Leopard上的g ++在以下代码中抛出链接错误

TEST.CPP

#include <iostream>
using namespace std;
#include <libavcodec/avcodec.h>    // required headers
#include <libavformat/avformat.h>
int main(int argc, char**argv) {
    av_register_all();             // offending library call
    return 0;
}

当我尝试使用以下命令编译它时

g++ test.cpp -I/usr/local/include -L/usr/local/lib \
-lavcodec -lavformat -lavutil -lz -lm -o test

我收到错误 未定义的符号:   “av_register_all()”,引自:       _main在ccUD1ueX.o中 ld:找不到符号 collect2:ld返回1退出状态

有趣的是,如果我有一个等效的C代码, test.c的

#include <stdio.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
int main(int argc, char**argv) {
    av_register_all();
    return 0;
}

gcc编译得很好

gcc test.c -I/usr/local/include -L/usr/local/lib \
-lavcodec -lavformat -lavutil -lz -lm -o test

我使用的是Mac OS X 10.6.5

$ g++ --version
i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5664)
$ gcc --version
i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5664)

FFMPEG的libavcodec,libavformat等是C库,我已经在我的机器上构建了它们,如下所示:

./configure --enable-gpl --enable-pthreads --enable-shared \
--disable-doc --enable-libx264
make && sudo make install

正如人们所料,libavformat确实包含符号av_register_all

$ nm /usr/local/lib/libavformat.a | grep av_register_all
0000000000000000 T _av_register_all
00000000000089b0 S _av_register_all.eh

我倾向于相信g ++和gcc对我机器上的库有不同的看法。 g ++无法选择合适的库。任何线索?

2 个答案:

答案 0 :(得分:12)

这可能是因为av_register_all函数不在extern "C"块中,因此当C ++编译器解释前向声明时,它的名称会被破坏。尝试将您的代码更改为:

#include <iostream>
using namespace std;
extern "C" {
#include <libavcodec/avcodec.h>    // required headers
#include <libavformat/avformat.h>
}
int main(int argc, char**argv) {
    av_register_all();             // offending library call
    return 0;
}

C ++编译器使用名称修改来允许使用不同参数覆盖相同的函数,但不是由C编译器执行(不提供函数覆盖)。

通常,用C编写并且可以包含在C ++文件中的头文件应具有以下结构以防止发生此类错误。您应该通知ffmpeg开发人员修改其代码:

// Standard includes guards
#ifndef INCLUDED_AVCODEC_H
#define INCLUDED_AVCODEC_H

// Protection against inclusion by a C++ file
#ifdef __cplusplus
extern "C" {
#endif

// C code
// ....

// Closing the protection against inclusion by a C++ file
#ifdef __cplusplus
}
#endif
#endif

[编辑]:我刚发现这是FFmpeg wiki上提到的。

答案 1 :(得分:0)

如果您的目标是安装ffmpeg,则始终可以使用MacPorts执行此操作。以下适用于我:

 sudo port install ffmpeg

您会发现许多针对UNIX的开源项目都会针对特定于Linux的假设,这些假设需要在Mac上正确配置和安装补丁。复制确定和创建此类补丁的工作通常是浪费时间,这就是使用MacPorts更有意义的原因。如果您想知道所需的具体修复是什么,您可以检查portfile以找出应用了哪些源代码补丁以及对构建命令的任何修改。