gcc returns 将 C 程序分解为多个文件时的未定义引用

gcc returns undefined reference when breaking up a C program into multiple files

有人向我提供了一个示例 C 文件,我想将其分解为一对 .c 文件和一个 .h 文件。拆分所有内容后,我无法编译程序,但我认为这是一个简单的解决方案。我的C生锈了。

capture.h

#ifndef __CAPTURE_H
#define __CAPTURE_H

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "master.h"
#include "pvcam.h"

static void AcquireStandard( int16 hCam, int16 num_frames, uns32 exp_time );
void setROI( rgn_type* roi, uns16 s1, uns16 s2, uns16 sbin, uns16 p1, uns16 p2, uns16 pbin );
void printROI( int16 roi_count, rgn_type* roi );
void print_pv_error( );
void setFullFrame( int16 hcam, rgn_type* roi );
#endif

capture.c

#include "capture.h"

void AcquireStandard( int16 hCam, int16 num_frames, uns32 exp_time ) {
... Does lots of stuff ...
}
... Many other functions, etc...

pixis.c

    #include "capture.h"

    int main(int argc, char **argv)
    {
        char cam_name[CAM_NAME_LEN];    /* camera name                    */
        int16 hCam;                     /* camera handle                  */
        int16 cam_selection;
        int16 num_frames, circ_buff_size, buffer_type;
        uns32 port, shtr_open_mode;
        uns32 enum_param, exp_time;
        int16 adc_index;
        int16 gain;
        uns16 exp_res_index;
        char *s;
        ..... snip .....
        AcquireStandard( hCam, num_frames, exp_time );
        pl_cam_close( hCam );
    pl_pvcam_uninit();
    return 0;
}

我删掉了很多不相关的东西。编译时,出现以下错误:

gcc -o pixis pixis.o capture.o -I/usr/local/pvcam/examples -lpvcam -ldl -lpthread -lraw1394
pixis.o: In function `main':
pixis.c:(.text+0x14a): undefined reference to `AcquireStandard'
collect2: ld returned 1 exit status
make: *** [pixis] Error 1

AcquireStandard在.o文件里,我用nm查了一下:

    nm capture.o 
00000000 t AcquireStandard
00000000 d _master_h_
00000004 d _pvcam_h_
         U fclose
         U fopen
         U free
         U fwrite
         U malloc
         U pl_error_code
         U pl_error_message
         U pl_exp_check_status
         U pl_exp_finish_seq
         U pl_exp_init_seq
         U pl_exp_setup_seq
         U pl_exp_start_seq
         U pl_exp_uninit_seq
         U pl_get_param
00000350 T printROI
00000440 T print_pv_error
         U printf
         U puts
00000489 T setFullFrame
000002d4 T setROI

现在我被难住了。过去几年 gcc 发生了什么变化还是我只是忘记了一些简单的细节?

这里的问题是 AcquireStandard() 函数最初的原型是 static,这意味着它的可见性被限制在实现它的文件中。在这个重构中,函数的可见性是必需的联系其他来源——但是 header 函数中仍然有 static 关键字。

另请注意 nm 命令的输出,特别是表示源中函数的这两行之间的差异:

00000000 t AcquireStandard
00000489 T setFullFrame

T 表示 object 文本中的函数具有全局可见性,而 t 表示可见性是局部的。

capture.h的原型上去掉static,问题就解决了。