C头文件和源文件混淆

C header and source file confusion

我自己写了一个我想重用的小模块。我得到了带有结构和函数声明的头文件 bitstream.h 以及带有实现的 bitstream.c。现在我想在我的其他程序中使用它,但不需要每次都手动编译 bitstream.c,就像你不必每次使用它都编译 stdio.h,但我不明白它工作。我的文件如下所示:

bitstream.c

#include "bitstream.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

bit_stream_t *fbit_stream(const char *path) {
    FILE *f;

    /* open file for reading */
    f = fopen(path, "rb");

    ...

bitstream.h

#ifndef BITSTREAM_H
#define BITSTREAM_H

#define EOS 0x0a

typedef struct {
    int size;
    int i_byte;
    unsigned char i_bit;
    unsigned char current_bit;
    unsigned char *bytes;
} bit_stream_t;

extern bit_stream_t *fbit_stream(const char *path);
extern unsigned char bit_stream_next(bit_stream_t *bs);
extern void bit_stream_close(bit_stream_t *bs);
extern void print_bit_stream(bit_stream_t *bs);

#endif

我将这两个文件放入 /usr/local/include(我在 Linux 机器上),现在我想在 main.c(其他地方,例如 /home/foo/main.c):

main.c

#include <bitstream.h>
#include <stdio.h>

int main(int argc, const char *argv[]) {
    if (argc != 2) {
        printf("Need 1 argument!\n");
        return 1;
    }

    bit_stream_t *my_bs;
    my_bs = fbit_stream(argv[1]);

    while (my_bs -> current_bit != EOS) {
        printf("%d", my_bs -> current_bit);
        bit_stream_next(my_bs);
    }

    bit_stream_close(my_bs);
    printf("\n");
    return 0;
}

当我尝试 gcc -Wall -o main.o main.c 我得到

/tmp/ccgdq66W.o: In function `main':
main.c:(.text+0x35): Undefined reference to `fbit_stream'
main.c:(.text+0x63): Undefined reference to `bit_stream_next'
main.c:(.text+0x7b): Undefined reference to `bit_stream_close'
collect2: error: ld returned 1 exit status

我做错了什么?在此先感谢您的帮助!

斯穆克

编译bitstream.c创建bitstream.o

gcc -Wall -c bitstream.c

编译 main.c 和 bitstream.o 以创建主程序(或 main.exe 如果在 winX 上)

gcc -Wall -o main main.c bitstream.o

您不需要每次都“编译”stdio.h 的原因是它的实现(以及更多)已经编译并在 GLibC 上运行。也就是说,glibc 是一个库(动态库),GCC link 每次编译程序时都会向它发送程序。您可以通过 运行:

检查
ldd hello
例如,

假设 hello 是一个使用 printf 的简单 Hello World! 程序。你会得到类似的东西:

linux-vdso.so.1 =>  (0x00007fff5f98d000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7e985b2000)
/lib64/ld-linux-x86-64.so.2 (0x00007f7e98977000)

请参阅第 2 行:libc.so.6,这是您的 GNU C 库,这就是您每次使用它时都不“编译”stdio.h 的原因。


一般情况

您想做的是实现您自己的库。因此,为了做到这一点,您可以做几件事。

  1. 您在 /usr/include 下创建了一个名为 MyLib 的目录,并将所有 headers 放在那里。这样您就可以使用 #include <MyLib/myHeader.h>.

    包含您的文件
  2. 方法 1: 将实现 myImp.c 编译到 object 文件中,然后将 object 放入文件夹,/my/libs/path/myImp.o,每次你想使用,你编译:

    gcc -o prog prog.c /my/libs/path/myImp.o

    注:prog.c必须#include <MyLibs/myHeader.h>

  3. 方法 2: 您可以使用实用程序 ar 制作一个存档,并将您所有的库都放在里面。检查它是 manual here。每次您想使用图书馆中的东西时,您可以 link 使用 .a 图书馆。

  4. 方法三:你可以做一个动态库,这会减少二进制文件的大小(linking .o and ar 库是静态的 linking,这意味着更大的二进制文件大小)。您可以使用 -fPIC(位置独立代码)gcc 标志和其他一些小东西来做到这一点。我会 link 一些资源。


您的具体情况

  1. gcc -c bitstream.c 编译 bitstream.c
  2. 将该文件放入 /home/you/myLibs/bitstream.o
  3. bitstream.h复制到/usr/include/MyLib/bitstream.h(你需要root
  4. 包括 #include <MyLib/bitstream.h>
  5. 编译你的程序:gcc -o main main.c ~/myLibs/bitstream.o

虽然这远非好事,但这会做你想做的。我建议您阅读有关如何组织自己的库等内容,查看 Rusty Russel's CCAN Library,这是关于如何构建 C 库的一个很好的起点。

真的推荐检查CCAN!


资源