Can';t使用C+编译C库+;使用g++; 我试图创建一个嵌入FFMPEG功能的C++程序。 为此,我举了一个FFMPEG示例,并使用g++重新编译它(只在需要时添加外部“C”)。 编译成功,但未定义符号的链接失败 cc -I/usr/include/x86_64-linux-gnu -Wall -g -fPIC -c -o bin/decode_video.o decode_video.cpp cc -Wl,--export-dynamic,--no-undefined -L /usr/lib/x86_64-linux-gnu/ -shared -lavdevice -lavutil -lavcodec bin/decode_video.o -o decode_video.so bin/decode_video.o: In function `decode(AVCodecContext*, AVFrame*, AVPacket*, char const*)': /home/admin1/ffmpeg_examples/decode_video.cpp:60: undefined reference to `avcodec_send_packet' /home/admin1/ffmpeg_examples/decode_video.cpp:67: undefined reference to `avcodec_receive_frame' bin/decode_video.o: In function `main': /home/admin1/ffmpeg_examples/decode_video.cpp:108: undefined reference to `av_packet_alloc' /home/admin1/ffmpeg_examples/decode_video.cpp:116: undefined reference to `avcodec_find_decoder' /home/admin1/ffmpeg_examples/decode_video.cpp:122: undefined reference to `av_parser_init' /home/admin1/ffmpeg_examples/decode_video.cpp:128: undefined reference to `avcodec_alloc_context3' /home/admin1/ffmpeg_examples/decode_video.cpp:139: undefined reference to `avcodec_open2' /home/admin1/ffmpeg_examples/decode_video.cpp:150: undefined reference to `av_frame_alloc' /home/admin1/ffmpeg_examples/decode_video.cpp:165: undefined reference to `av_parser_parse2' /home/admin1/ffmpeg_examples/decode_video.cpp:184: undefined reference to `av_parser_close' /home/admin1/ffmpeg_examples/decode_video.cpp:185: undefined reference to `avcodec_free_context' /home/admin1/ffmpeg_examples/decode_video.cpp:186: undefined reference to `av_frame_free' /home/admin1/ffmpeg_examples/decode_video.cpp:187: undefined reference to `av_packet_free'

Can';t使用C+编译C库+;使用g++; 我试图创建一个嵌入FFMPEG功能的C++程序。 为此,我举了一个FFMPEG示例,并使用g++重新编译它(只在需要时添加外部“C”)。 编译成功,但未定义符号的链接失败 cc -I/usr/include/x86_64-linux-gnu -Wall -g -fPIC -c -o bin/decode_video.o decode_video.cpp cc -Wl,--export-dynamic,--no-undefined -L /usr/lib/x86_64-linux-gnu/ -shared -lavdevice -lavutil -lavcodec bin/decode_video.o -o decode_video.so bin/decode_video.o: In function `decode(AVCodecContext*, AVFrame*, AVPacket*, char const*)': /home/admin1/ffmpeg_examples/decode_video.cpp:60: undefined reference to `avcodec_send_packet' /home/admin1/ffmpeg_examples/decode_video.cpp:67: undefined reference to `avcodec_receive_frame' bin/decode_video.o: In function `main': /home/admin1/ffmpeg_examples/decode_video.cpp:108: undefined reference to `av_packet_alloc' /home/admin1/ffmpeg_examples/decode_video.cpp:116: undefined reference to `avcodec_find_decoder' /home/admin1/ffmpeg_examples/decode_video.cpp:122: undefined reference to `av_parser_init' /home/admin1/ffmpeg_examples/decode_video.cpp:128: undefined reference to `avcodec_alloc_context3' /home/admin1/ffmpeg_examples/decode_video.cpp:139: undefined reference to `avcodec_open2' /home/admin1/ffmpeg_examples/decode_video.cpp:150: undefined reference to `av_frame_alloc' /home/admin1/ffmpeg_examples/decode_video.cpp:165: undefined reference to `av_parser_parse2' /home/admin1/ffmpeg_examples/decode_video.cpp:184: undefined reference to `av_parser_close' /home/admin1/ffmpeg_examples/decode_video.cpp:185: undefined reference to `avcodec_free_context' /home/admin1/ffmpeg_examples/decode_video.cpp:186: undefined reference to `av_frame_free' /home/admin1/ffmpeg_examples/decode_video.cpp:187: undefined reference to `av_packet_free',c++,c,ffmpeg,g++,cc,C++,C,Ffmpeg,G++,Cc,检查nm时,我发现没有名字在起作用,因此extern C似乎工作得很好: nm bin/decode_video.o U avcodec_alloc_context3 U avcodec_find_decoder U avcodec_free_context U avcodec_open2 U avcodec_receive

检查nm时,我发现没有名字在起作用,因此extern C似乎工作得很好:

nm bin/decode_video.o 

                 U avcodec_alloc_context3
                 U avcodec_find_decoder
                 U avcodec_free_context
                 U avcodec_open2
                 U avcodec_receive_frame
                 U avcodec_send_packet
                 U av_frame_alloc
                 U av_frame_free
                 U av_packet_alloc
                 U av_packet_free
                 U av_parser_close
                 U av_parser_init
                 U av_parser_parse2
                 U exit
                 U fclose
                 U feof
                 U fflush
                 U fopen
                 U fprintf
                 U fread
                 U fwrite
                 U _GLOBAL_OFFSET_TABLE_
000000000000026f T main
                 U memset
                 U printf
                 U snprintf
                 U __stack_chk_fail
                 U stderr
                 U stdout
00000000000000a3 t _ZL6decodeP14AVCodecContextP7AVFrameP8AVPacketPKc
0000000000000000 t _ZL8pgm_savePhiiiPc
在检查库时,对于其中一个“缺失”符号,我可以看到它已实现

nm /usr/lib/x86_64-linux-gnu/libavcodec.a | grep avcodec_send_packet

00000000000033e0 T avcodec_send_packet
                 U avcodec_send_packet
当用C编译时,它工作得非常完美(当然没有外部C),这让我想知道我缺少了什么

下面查找FFMPEG示例代码以供参考(decode_video.cpp):

#包括
#包括
#包括
外部“C”
{
#包括
}
#定义INBUF_尺寸4096
静态void pgm_save(无符号字符*buf、int wrap、int xsize、int ysize、,
字符*文件名)
{
文件*f;
int i;
f=fopen(文件名,“w”);
fprintf(f,“P5\n%d%d\n%d\n”,xsize,ysize,255);
对于(i=0;i=0){
ret=avcodec_接收_帧(dec_ctx,帧);
如果(ret==AVERROR(EAGAIN)| | ret==AVERROR_EOF)
返回;
否则如果(ret<0){
fprintf(stderr,“解码过程中的错误”);
出口(1);
}
printf(“保存帧%3d\n”,dec\u ctx->帧号);
fflush(stdout);
/*图片由解码器分配,无需重新分配
释放它*/
snprintf(buf,sizeof(buf),%s-%d”,文件名,dec\u ctx->帧号);
pgm_保存(帧->数据[0],帧->线宽[0],
框架->宽度,框架->高度,基本单位);
}
}
int main(int argc,字符**argv)
{
常量字符*文件名,*输出文件名;
const AVCodec*编解码器;
AVCodecParserContext*解析器;
AVCodecContext*c=NULL;
文件*f;
AVFrame*frame;
uint8_t inbuf[inbuf_SIZE+AV_INPUT_BUFFER_PADDING_SIZE];
uint8_t*数据;
大小\u t数据\u大小;
int ret;
AVPacket*pkt;
if(argc id);
if(!解析器){
fprintf(stderr,“找不到解析器”\n);
出口(1);
}
c=avcodec\u alloc\u context3(编解码器);
如果(!c){
fprintf(stderr,“无法分配视频编解码器上下文\n”);
出口(1);
}
/*对于某些编解码器,如msmpeg4和mpeg4,宽度和高度
必须在那里初始化,因为此信息不可用
在比特流中可用*/
/*打开它*/
if(avcodec_open2(c,codec,NULL)<0){
fprintf(stderr,“无法打开编解码器”\n);
出口(1);
}
f=fopen(文件名,“rb”);
如果(!f){
fprintf(stderr,“无法打开%s\n”,文件名);
出口(1);
}
frame=av_frame_alloc();
如果(!帧){
fprintf(stderr,“无法分配视频帧”\n);
出口(1);
}
而(!feof(f)){
/*从输入文件中读取原始数据*/
数据大小=fread(inbuf,1,inbuf大小,f);
如果(!数据大小)
打破
/*使用解析器将数据拆分为帧*/
数据=inbuf;
而(数据大小>0){
ret=av_parser_parse2(parser,c,&pkt->data,&pkt->size,
数据、数据大小、AV\U NOPTS\U值、AV\U NOPTS\U值,0);
如果(ret<0){
fprintf(stderr,“解析时出错\n”);
出口(1);
}
数据+=ret;
数据大小-=ret;
如果(包装->尺寸)
解码(c,帧,pkt,outfilename);
}
}
/*刷新解码器*/
解码(c,帧,空,输出文件名);
fclose(f);
av_解析器_close(解析器);
avcodec_free_上下文(&c);
av_无帧(&帧);
av_数据包免费(&pkt);
返回0;
}

感谢@WhozCraig帮我解决了这个问题。 我在链接时使用了错误的标志,认为我保留了完整的库符号,但是它是错误的标志。所以linker只传递了一次,对象的顺序是错误的(因为我自然认为这无关紧要) 要保留完整的库符号,请将整个存档传递给链接器:

-Wl,--whole-archive

假设您实际安装了正确的LIB,请尝试将您的LIB(
-lname
)放在构建行中的对象文件之后。这确实有效!你可以发布一个详细的答案来解释原因吗?仅在这个网站上就至少有十几个这样的副本,但我没有时间去寻找它们。它归结为链接器在链接行上从左到右抛出以前遇到的代码未引用的内容。也就是说,以前遇到的libs和obj不使用的lib中的所有内容都将丢弃这些函数,从而无法在以后使用。通过移动它们,你实际上是在告诉链接器“当你看到av_foo”时,你可能还不知道它是什么,但它正在到来;我保证。“然后您最终通过
-lname
实现了这一承诺,但我定义了导出动态以避免这种情况,假设最终对象将保留所有符号,而不仅仅是使用的符号。我的推理错了吗?那是为了你的图书馆,而不是你正在消费的图书馆。顺便说一句,这不是普遍的。并非所有链接器都这样做。然而,海湾合作委员会(gcc)却因此臭名昭著。
-Wl,--whole-archive