链接库标题时未定义的引用....

时间:2014-09-30 12:29:08

标签: c gcc linker

我正在尝试编译一个使用libvncserver的C程序,但无论我做什么我都会遇到undefined reference错误,我遇到麻烦的库是rfb/rfb.h

vnc.c代码(从here复制):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rfb/rfb.h>
#define WIDTH 640
#define HEIGHT 480
#define BPP 4
/* 15 frames per second (if we can) */
#define PICTURE_TIMEOUT (1.0/15.0)
/*
* throttle camera updates
*/
int TimeToTakePicture() {
static struct timeval now={0,0}, then={0,0};
double elapsed, dnow, dthen;
gettimeofday(&now,NULL);
dnow = now.tv_sec + (now.tv_usec /1000000.0);
dthen = then.tv_sec + (then.tv_usec/1000000.0);
elapsed = dnow - dthen;
if (elapsed > PICTURE_TIMEOUT)
memcpy((char *)&then, (char *)&now, sizeof(struct timeval));
return elapsed > PICTURE_TIMEOUT;
}
/*
* simulate grabbing a picture from some device
*/
int TakePicture(unsigned char *buffer)
{
static int last_line=0, fps=0, fcount=0;
int line=0;
int i,j;
struct timeval now;
/*
* simulate grabbing data from a device by updating the entire framebuffer
*/
for(j=0;j<HEIGHT;++j) {
for(i=0;i<WIDTH;++i) {
buffer[(j*WIDTH+i)*BPP+0]=(i+j)*128/(WIDTH+HEIGHT); /* red */
buffer[(j*WIDTH+i)*BPP+1]=i*128/WIDTH; /* green */
buffer[(j*WIDTH+i)*BPP+2]=j*256/HEIGHT; /* blue */
}
buffer[j*WIDTH*BPP+0]=0xff;
buffer[j*WIDTH*BPP+1]=0xff;
buffer[j*WIDTH*BPP+2]=0xff;
}
/*
* simulate the passage of time
*
* draw a simple black line that moves down the screen. The faster the
* client, the more updates it will get, the smoother it will look!
*/
gettimeofday(&now,NULL);
line = now.tv_usec / (1000000/HEIGHT);
if (line>HEIGHT) line=HEIGHT-1;
memset(&buffer[(WIDTH * BPP) * line], 0, (WIDTH * BPP));
/* frames per second (informational only) */
fcount++;
if (last_line > line) {
fps = fcount;
fcount = 0;
}
last_line = line;
fprintf(stderr,"%03d/%03d Picture (%03d fps)\r", line, HEIGHT, fps);
/* success! We have a new picture! */
return (1==1);
}
/*
* Single-threaded application that interleaves client servicing with taking
* pictures from the camera. This way, we do not update the framebuffer
* while an encoding is working on it too (banding, and image artifacts).
*/
int main(int argc,char** argv)
{
long usec;
rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,WIDTH,HEIGHT,8,3,BPP);
if(!server)
return 0;
server->desktopName = "Live Video Feed Example";
server->frameBuffer=(char*)malloc(WIDTH*HEIGHT*BPP);
server->alwaysShared=(1==1);
/* Initialize the server */
rfbInitServer(server);
/* Loop, processing clients and taking pictures */
while (rfbIsActive(server)) {
if (TimeToTakePicture())
if (TakePicture((unsigned char *)server->frameBuffer))
rfbMarkRectAsModified(server,0,0,WIDTH,HEIGHT);
usec = server->deferUpdateTime*1000;
rfbProcessEvents(server,usec);
}
return(0);
}

编译器输出:

sudo gcc -g -Wall -Wextra -O2 vnc.c

/tmp/cc7dpMCs.o: In function `main':
/home/arcm/Projects/c/vnc.c:77: undefined reference to `rfbGetScreen'
/home/arcm/Projects/c/vnc.c:84: undefined reference to `rfbInitServerWithPthreadsAndZRLE'
/home/arcm/Projects/c/vnc.c:91: undefined reference to `rfbProcessEvents'
/home/arcm/Projects/c/vnc.c:86: undefined reference to `rfbIsActive'
/home/arcm/Projects/c/vnc.c:89: undefined reference to `rfbMarkRectAsModified'
collect2: error: ld returned 1 exit status

我安装了libvncserver0libvncserver-dev,我正在使用ubuntu 14.04。 我试过了:

sudo gcc -g -Wall -Wextra -O2 vnc.c -lm
sudo gcc -g -Wall -Wextra -O2 vnc.c -ldl
sudo gcc -g -Wall -Wextra -O2 -ldl vnc.c
sudo gcc -g -Wall -Wextra -O2 -I/usr/include/rfb -L/usr/include/rbf/rfb.h vnc.c 
sudo gcc -g -Wall -Wextra -O2 -I/usr/include/rfb vnc.c
sudo gcc -g -Wall -Wextra -O2 -L/usr/include/rbf/rfb.h vnc.c
sudo gcc -g -Wall -Wextra -O2 /usr/include/rbf/rfb.h vnc.c
sudo gcc -g -Wall -Wextra -O2 -L/usr/include/rbf/rfb.h -ldl vnc.c

但我每次都会遇到同样的错误。我做错了什么,我该如何解决?

1 个答案:

答案 0 :(得分:7)

你没有&#34;链接&#34;一个库头,你包含它,以便编译器在编译时看到库的声明,并且知道rfbGetScreen()是一个需要这样的函数 - 这个和那个类型的参数很多,并返回一个rfbScreenInfoPtr 如何执行此操作(函数的定义)对编译器并不重要。它只是为该函数添加了引用,留给链接器解析。 (注意这里的词汇。)

将已编译的代码链接到库二进制文件。这是由链接器在不同的(以及稍后的)步骤中完成的,只是发生以与编译源(gcc)相同的前端支持。在此步骤中,您的代码实际使用(引用)的任何库函数都是已解析,方法是将它们从指定的库中链接。

这就是......

sudo gcc -g -Wall -Wextra -O2 vnc.c

...仅链接标准库和运行时,因为那里没有特定的链接指令。

这就是......

-L/usr/include/rbf/rfb.h

...是无稽之谈,因为-L用于提供目录,其中应该查找库二进制文件(如果有问题的库安装在标准位置,则不需要)

实际链接指令为-l。如果您声明-lfoo,则会搜索库libfoo以查找任何未定义的引用。

这就是......

-ldl

...正在关联libdl,您应该能够推断出......

-lvncserver

...正是您正在寻找的(假设<rfb/rfb.h>确实引用了libvncserver,我不知道。

请注意,链接器按照命令行中给出的顺序处理库,因此您需要在 -lvncserver之后声明vnc.c ,因为只有这样才能链接器知道它应该在libvncserver中寻找哪些未定义的引用。

永远不会,永远运行编译器为sudo为什么在{.....}的名称中你认为这个有必要吗?