Search code examples
c++gccg++libavformat

gcc compiles libavformat code, but g++ does not


In order to determine the video duration for a given file, I use libavformat. My program looks as follows:

#include <stdio.h>
#include <libavformat/avformat.h>
#include <libavutil/dict.h>
int main (int argc, char **argv) {
    AVFormatContext *fmt_ctx = NULL;
    int ret;
    if (argc != 2) {
        printf("usage: %s <input_file>\n", argv[0]);
        return 1;
    }
    av_register_all();
    if ((ret = avformat_open_input(&fmt_ctx, argv[1], NULL, NULL)))
        return ret;
    int64_t duration = fmt_ctx->duration;
    int hours, mins, secs;
    secs  = duration / AV_TIME_BASE;
    mins  = secs / 60;
    secs %= 60;
    hours = mins / 60;
    mins %= 60;
    printf("Duration: %02d:%02d:%02d\n", hours, mins, secs);
    avformat_free_context(fmt_ctx);
    return 0;
}

My problem is that while gcc compiles the code just fine, g++ does so without complaint as well but the created object file can neither be linked by gcc nor g++. Or to be more precise:

gcc -c duration.c
gcc -o duration duration.o -lavformat
./duration my_movie.mp4

works. But this

g++ -c duration.c # "works" as in "g++ does not complain"
g++ -o duration duration.o -lavformat # (gcc produces the same output after compiling with g++)
duration.o: In function `main':
duration.c:(.text+0x41): undefined reference to `av_register_all()'
duration.c:(.text+0x62): undefined reference to `avformat_open_input(AVFormatContext**, char const*, AVInputFormat*, AVDictionary**)'
duration.c:(.text+0x18c): undefined reference to `avformat_free_context(AVFormatContext*)'
collect2: error: ld returned 1 exit status

does not work. This leads me to the conclusion that g++ does not produce code that can be linked properly (in this instance).

I would really like to make this work with g++ because it is part of a bigger c++ project and it would be a bit of a mess always having to compile files that make use of this library with gcc instead. Does anyone know why g++ won't compile this program correctly?


Solution

  • This error tells us all we need to know:

    duration.c:(.text+0x62): undefined reference to `avformat_open_input(AVFormatContext**, char const*, AVInputFormat*, AVDictionary**)'
    

    The linker wouldn't know the type of the arguments unless it thought it was a C++ function. So you need to do this:

    extern "C" {
    #include <libavformat/avformat.h>
    #include <libavutil/dict.h>
    }
    

    Normally, the header files would have the extern "C" part in them. The FFmpeg project doesn't seem interested in doing this. Some of the headers may include C constructions which are not compatible with C++, as noted in FFmpeg ticket #3626.

    If you run into such problems, you would need to write a shim in C.