我正在尝试制作一个属于我的静态库。假设有两个文件:stack.h
存储我想存储在 ./include
文档中的声明,stack.c
实现定义,main.c
调用文件中的函数stack.h
。
使用这些说明制作 stack.a
文件,我想将其存储在 ./lib
中:
>> gcc -c stack.c
>> ar -cq libstack.a stack.o
>> mv stack.h include
>> mv libstack.a lib
如果我想将 main.c
与我的 libstack.a
链接,我将如何处理 gcc
?我需要把这个库放到 PATH 中吗?如果是这样,该怎么做?
如果下一步,我想做我的动态库 .so
文件,谁能给点建议?
答案 0 :(得分:1)
C 库
一般来说,库是从许多库源文件创建的,或者构建为静态链接到使用它们的可执行文件的存档文件 (libmine.a),或者构建为动态链接的共享对象文件 (libmine.so)到使用它们的可执行文件中。要链接这些类型的库,请使用 gcc
命令行选项 -L
作为库文件的路径,并使用 -l
链接库(.so 或 .a) :
-L{path to file containing library} -l${library name}
例如,如果我在 /home/newhall/lib/
中有一个名为 libmine.so 的库,那么我会执行以下操作将其链接到我的程序中:
$ gcc -o myprog myprog.c -L/home/newhall/lib -lmine
您可能还需要指定并包含路径,以便编译器可以找到库头文件:-I /home/newhall/include
如果您创建了自己的共享对象文件并且没有将它们安装在 /usr/lib
中,那么您需要设置 LD_LIBRARY_PATH 环境变量,以便运行时链接程序可以在运行时找到它们并加载它们。
例如,如果我将 .so 文件放在 lib
目录中名为 home
的目录中,我会将 LD_LIBRARY_PATH
环境设置为以下内容:
# 如果运行 bash:
>> export LD_LIBRARY_PATH=/home/newhall/lib:$LD_LIBRARY_PATH
# 如果运行 tcsh:
>> setenv LD_LIBRARY_PATH /home/newhall/lib:$LD_LIBRARY_PATH
使用和链接库代码
要使用未通过以下方式自动链接到您的程序的库 编译器,你需要
test.c
).o
文件中的代码链接到您的可执行文件中:步骤 1:在程序中添加包含行(#include "somelib.h") 源文件(例如 test.c)。
第 2 步:将程序的 .c 文件与库对象文件链接 (即,将 somelib.o 文件指定为 gcc 的命令行参数):
>> gcc -o myprog test.c somelib.o
生成的可执行文件 (myprog
) 将包含所有机器码
test.c 中定义的函数加上调用的任何 mylib 库函数。
创建和使用您自己的库代码
要创建代码库,您需要执行以下操作:
(1) 为你的库创建一个接口:mylib.h
(2) 为你的库创建一个实现:mylib.c
(3) 创建一个可以与使用您的库的程序链接的库对象文件 (.o)
3a。或从许多 .o 文件创建一个共享对象文件 (.so),这些文件可以与使用您的库的程序动态链接
3b。或从许多 .o 文件创建一个存档文件 (.a),这些文件可以与使用您的库的程序静态链接
(4) 在其他 C 代码中使用库: (a) #include "mylib.h" (b) 将库代码中的链接到 a.out 文件
(5) 设置 LD_LIBRARY_PATH 环境变量,用于在运行时查找非标准位置的共享对象
详情:
(1) 接口:库的头文件应包含库导出的所有内容的定义:
带有库函数用户注释的函数原型
库导出的类型和全局变量的定义
你应该在头文件的内容周围有“样板”代码(#ifndef ... #endif),以确保预处理器只包含一次 mylib.h 文件。
示例 .h 文件可能如下所示:
#ifndef MYLIB_H_ // _MYLIB_H_ is not allowed.
#define MYLIB_H_
// a constant definition exported by library:
#define MAX_FOO 20
// a type definition exported by library:
struct foo_struct {
int x;
float y;
};
typedef struct foo_struct foo_struct;
// a global variable exported by library
// "extern" means that this is not a variable declaration, it
// just defines that a variable named total_foo of type int
// exits and you can use it (its declaration is in some library source file)
extern int total_foo;
// a function prototype for a function exported by library:
extern int foo(float y, float z); // a very bad function name
#endif
(2) 实现:创建一个 mylib.c 文件,其中 #includes "mylib.h" 并包含库中每个函数的实现。
#include "mylib.h"
...
int total_foo;
int foo(float y, float z) {
...
}
(3) 创建一个 LIBRARY OBJECT FILE,它可以链接到使用你的库的其他程序中(使用 gcc 的 -c 选项告诉它只是创建一个目标文件(一个 .o 文件)而不是一个可执行文件:
>> gcc -o mylib.o -c mylib.c
然后您可以将 mylib.o 文件用作“库文件”并将其静态链接到使用它的其他程序,或者...
>> gcc -shared -o libmylib.so mylib.o blah.o grr.o -lm
(4) 在其他程序中使用该库:
步骤 1:在所有使用库定义(例如 test.c)的程序源文件中添加包含行(#include "mylib.h")。
第 2 步:将程序的 .c 文件与库对象文件链接 (即指定 mylib.o 文件作为 gcc 的命令行参数):
gcc test.c mylib.o
OR to link in libmylib.so (or libmylib.a):
gcc test.c -lmylib
OR to link with a library not in the standard path:
gcc test.c -L/home/newhall/lib -lmylib
The resulting a.out out will contain machine code for all the functions
defined in test.c plus any mylib library functions that are called by
the test.c code.
(5) 运行与共享目标文件链接的可执行文件:
如果共享对象文件不在/usr/lib中,那么你需要设置你的 LD_LIBRARY_PATH 环境变量,以便运行时链接器可以找到 并在运行时将您的 .so 文件加载到可执行文件中:
>> export LD_LIBRARY_PATH=/home/newhall/lib:$LD_LIBRARY_PATH
>> setenv LD_LIBRARY_PATH /home/newhall/lib:$LD_LIBRARY_PATH
答案 1 :(得分:0)
还有一个有用的链接:demo for making libraries