开发者

g++ Linking Error on Mac while compiling FFMPEG

g++ on Snow Leopard is throwing linking errors on the following piece of code

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;
}

When I try to compile this using the following command

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

I get the error Undefined symbols: "av_register_all()", referenced from: _main in ccUD1ueX.o ld: symbol(s) not found collect2: ld returned 1 exit status

Interestingly, if I have an equivalent c code, 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 compiles it just fine

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

I am using 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's libavcodec, libavformat etc. are C libraries and I have built them on my machine like thus:

./configure --enable-gpl --enable-pthr开发者_如何转开发eads --enable-shared \
--disable-doc --enable-libx264
make && sudo make install

As one would expect, libavformat indeed contains the symbol av_register_all

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

I am inclined to believe g++ and gcc have different views of the libraries on my machine. g++ is not able to pick up the right libraries. Any clue?


This is probably because the av_register_all function is not in an extern "C" block and thus when the forward declaration is interpreted by the C++ compiler, it's name is mangled. Try to change your code to:

#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;
}

The name mangling is used by the C++ compilers to allow override of the same function with differents arguments, but is not performed by C compilers (which do not offer function overriding).

Generally, the headers that are written in C and can be included in C++ file should have the following structure to prevent such bugs to occurs. You should probably inform the ffmpeg developpers to have their code modified:

// 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

[Edit]: I just found out that this is mentioned on FFmpeg wiki.


If your goal is to install ffmpeg, you can always do so using MacPorts. The following works for me:

 sudo port install ffmpeg

You will find that a lot of open source projects targetting UNIX make Linux-specific assumptions that require patches to properly configure and install on the Mac. It is generally a waste of time to replicate the work of determining and creating such patches, which is why it makes more sense to use MacPorts. If you care to know what the specific fix needed is, you can examine the portfile to find out both what source code patches were applied as well as any modifications to the build commands.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜