共计 3445 个字符,预计需要花费 9 分钟才能阅读完成。
写过 C /C++ 的程序员都知道要想程序正确的编译通过,需要引用一些通用的头文件,如 #include <stdio.h>,有时我们自己也写过好多具有独立功能通用的函数,那么我们怎么使用自己写好的通用函数库呢,下面我将以数据结构中我们常见的循环链表为例,一步一步讲解怎么建立自己的 C 库:
-
首先在根目录下创建一个名叫 mylib 的目录
mkdir /mylib
-
在目录中建立如下文件
[root@chin mylib]# tree -T .
|-- Makefile
|-- cutil.h
|-- cycle.c
|-- list.h
`-- man
其中 cutil.h 是通用头文件,所有其它定义的头文件都包含于其中。Cycle.c 是创建循环链表的相关函数实现,list.h 中是创建循环链表的函数声明。Man 目录用于说明各函数的作用与用法,考虑到篇幅,本文中省略此步。
-
各文件内容如下所示
1) Makefile 内容
BIN = libcutil.so
LDFLAGS = -lpthread
CFLAGS += -g -Wall -shared -fPIC
LIBS = -L .
all:$(BIN)
OBJECT=${patsubst %.c, %.o, ${wildcard *.c}}
.c.o:
${CC} -o $@ -c $? ${CFLAGS}
$(BIN):${OBJECT}
${CC} $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS)
install:
cp ./*.so /usr/lib
.PHONY:clean
clean:
-rm *.o $(BIN)
2) 下面是 cycle.c 的内容
#include "cutil.h"
list create_list_head( void )
{
list head = NULL;
head = (list)malloc(sizeof *head);
head->item = 1;
return head;
}
void insert_cycle_node(list p,int num)
{
int i;
list s;
s = p;
for(i = 2;i<= num ;i++)
{ s->next =(list)malloc(sizeof *s);
s = s->next;
s->item = i;
}
s->next = p;
}
void print_cycle_list(list p)
{
list s;
s = p;
int count = 1;
while(s->next != p)
{ printf("The %dth Item value is:%d\n",count++,s->item);
s = s->next;
}
printf("The %dth Item value is:%d\n",count,s->item);
}
void destroy_cycle_list(list p)
{
list s,ptmp;
s = p;
while(s->next != p)
{
ptmp = s;
s = s->next;
free(ptmp);
}
free(s);
}
3) list.h 内容如下:
#ifndef __LIST_H__
#define __LIST_H__
typedef struct _list *list;
struct _list{
int item;
list next;
};
list create_list_head( void ); // 创建链表头结点
void insert_cycle_node( list p,int num ); // 插入循环链表结点
void print_cycle_list( list p ); // 打印循环链表
void destroy_cycle_list( list p); // 销毁循环链表
#endif
4) cutil.h 内容如下:
#ifndef __CUTIL_H__
#define __CUTIL_H__
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "list.h"
#endif
-
编译生成动态库
make && make install
将动态库拷贝到系统标准库路径下 /lib 或/usr/lib目录均可,不然后面运行程序的时候会报找不到动态库的错误。
-
建立自己的工作目录
mkdir /home/code/cycle -p
-
创建以下文件
[root@chin sort_list]# tree -T .
|-- Makefile
`-- cycle.c
编辑 Makefile 文件如下:
BIN = cycle
CFLAGS = -g -Wall
LDFLAGS = -lcutil
INCLUDE = -I/mylib
LIBS = -L /mylib
all:$(BIN)
OBJECT=${patsubst %.c, %.o, ${wildcard *.c}}
.c.o:
${CC} -o $@ -c $? ${CFLAGS} ${INCLUDE}
$(BIN):${OBJECT}
${CC} -o $@ $^ ${INCLUDE} $(LDFLAGS) $(LIBS)
.PHONY:clean
clean:
-rm *.o $(BIN)
编辑 cycle.c 内容如下:
#include "cutil.h"
// 以 "" 引用的头文件,程序编译时会首先在当前目录下寻找此头文件,如果没找到将会去我们指定的路径中寻找。int main(int argc,char *argv[])
{
list phead;
int n;
printf("How many node do you want to create:");
scanf("%d",&n);
phead = create_list_head(); // 创建带头结点的链表
insert_cycle_node(phead,n); // 插入循环链表结点
print_cycle_list(phead); // 打印循环链表结点
destroy_cycle_list(phead); // 释放链表
return 0;
}
-
编译并运行
[root@chin sort_list]# make
cc -o cycle.o -c cycle.c -g -Wall -I/mylib
cc -o cycle cycle.o -I/mylib -lcutil -L /mylib
[root@chin sort_list]# ./cycle
How many node do you want to create:5
The 1th Item value is:1
The 2th Item value is:2
The 3th Item value is:3
The 4th Item value is:4
The 5th Item value is:5
-
总结
最后运行程序后达到了我们预期的单循环链表的效果,如果以后需要再次拓展库函数,我们只需要的 mylib 目录下建立相应的.c 和.h 文件,并把.h 文件包含进 cutil.h 这个头文件中即可。这样如果我们在平时训练中写过一些通用的函数,就可以把它加入到我们自己的 C 库当中了。
当然,以上所说的几步也只是一些简单的手段,如果考虑到不同平台之间的移植性就得做更多的 #ifdef ...#define...#endif 等成对的预处理了。OK!Enjoy your programming!
