Ошибка компоновки g ++ на Mac при компиляции FFMPEG - PullRequest
3 голосов
/ 03 января 2011

g ++ в Snow Leopard выдает ошибки связывания в следующем фрагменте кода

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 ]

12 голосов
/ 03 января 2011

Вероятно, это связано с тем, что функция 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 .

0 голосов
/ 03 января 2011

Если ваша цель - установить ffmpeg, вы всегда можете сделать это, используя MacPorts .Следующее работает для меня:

 sudo port install ffmpeg

Вы обнаружите, что многие проекты с открытым исходным кодом, ориентированные на UNIX, делают специфичные для Linux предположения, которые требуют исправлений для правильной настройки и установки на Mac.Обычно копирование работы по определению и созданию таких исправлений является пустой тратой времени, поэтому имеет смысл использовать MacPorts.Если вы хотите узнать, какое именно исправление необходимо, вы можете проверить файл порта, чтобы выяснить, какие исправления исходного кода были применены, а также любые изменения в командах сборки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...