Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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-pthreads --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?

like image 215
S B Avatar asked Sep 01 '26 07:09

S B


1 Answers

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.

like image 125
Sylvain Defresne Avatar answered Sep 04 '26 11:09

Sylvain Defresne