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
的原因。
一般情况
您想做的是实现您自己的库。因此,为了做到这一点,您可以做几件事。
您在 /usr/include
下创建了一个名为 MyLib
的目录,并将所有 headers 放在那里。这样您就可以使用 #include <MyLib/myHeader.h>
.
包含您的文件
方法 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>
。
方法 2: 您可以使用实用程序 ar
制作一个存档,并将您所有的库都放在里面。检查它是 manual here。每次您想使用图书馆中的东西时,您可以 link 使用 .a
图书馆。
方法三:你可以做一个动态库,这会减少二进制文件的大小(linking .o and ar
库是静态的 linking,这意味着更大的二进制文件大小)。您可以使用 -fPIC
(位置独立代码)gcc
标志和其他一些小东西来做到这一点。我会 link 一些资源。
您的具体情况
- 用
gcc -c bitstream.c
编译 bitstream.c
。
- 将该文件放入
/home/you/myLibs/bitstream.o
。
- 将
bitstream.h
复制到/usr/include/MyLib/bitstream.h
(你需要root)
- 包括
#include <MyLib/bitstream.h>
- 编译你的程序:
gcc -o main main.c ~/myLibs/bitstream.o
。
虽然这远非好事,但这会做你想做的。我建议您阅读有关如何组织自己的库等内容,查看 Rusty Russel's CCAN Library,这是关于如何构建 C 库的一个很好的起点。
我真的推荐检查CCAN!
资源
我自己写了一个我想重用的小模块。我得到了带有结构和函数声明的头文件 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
的原因。
一般情况
您想做的是实现您自己的库。因此,为了做到这一点,您可以做几件事。
您在
包含您的文件/usr/include
下创建了一个名为MyLib
的目录,并将所有 headers 放在那里。这样您就可以使用#include <MyLib/myHeader.h>
.方法 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>
。方法 2: 您可以使用实用程序
ar
制作一个存档,并将您所有的库都放在里面。检查它是 manual here。每次您想使用图书馆中的东西时,您可以 link 使用.a
图书馆。方法三:你可以做一个动态库,这会减少二进制文件的大小(linking .o and
ar
库是静态的 linking,这意味着更大的二进制文件大小)。您可以使用-fPIC
(位置独立代码)gcc
标志和其他一些小东西来做到这一点。我会 link 一些资源。
您的具体情况
- 用
gcc -c bitstream.c
编译bitstream.c
。 - 将该文件放入
/home/you/myLibs/bitstream.o
。 - 将
bitstream.h
复制到/usr/include/MyLib/bitstream.h
(你需要root) - 包括
#include <MyLib/bitstream.h>
- 编译你的程序:
gcc -o main main.c ~/myLibs/bitstream.o
。
虽然这远非好事,但这会做你想做的。我建议您阅读有关如何组织自己的库等内容,查看 Rusty Russel's CCAN Library,这是关于如何构建 C 库的一个很好的起点。
我真的推荐检查CCAN!