注:转载请标明出处。联系方式:E-mail:411239339@qq.com
写过C/C++的程序员都知道要想程序正确的编译通过,需要引用一些通用的头文件,如#include ,有时我们自己也写过好多具有独立功能通用的函数,那么我们怎么使用自己写好的通用函数库呢,下面我将以数据结构中我们常见的循环链表为例,一步一步讲解怎么建立自己的C库:
1.首先在根目录下创建一个名叫mylib的目录
#mkdir /mylib
2.在目录中建立如下文件
[root@chin mylib]# tree -T .
|-- Makefile
|-- cutil.h
|-- cycle.c
|-- list.h
`-- man
其中cutil.h是通用头文件,所有其它定义的头文件都包含于其中。Cycle.c是创建循环链表的相关函数实现,list.h中是创建循环链表的函数声明。Man目录用于说明各函数的作用与用法,考虑到篇幅,本文中省略此步。
3.各文件内容如下所示:
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 $(BIN) $^ $(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
#include
#include
#include "list.h"
#endif
4.编译生成动态库libcutil.so
#make&make install
5.建立自己的工作目录/home/code/cycle
#mkdir /home/code/cycle -p
6.创建以下文件
[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;
}
7.编译并运行
[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
8.总结
最后运行程序后达到了我们预期的单循环链表的效果,如果以后需要再次拓展库函数,我们只需要的mylib目录下建立相应的.c和.h文件,并把.h文件包含进cutil.h这个头文件中即可。这样如果我们在平时训练中写过一些通用的函数,就可以把它加入到我们自己的C库当中了。
当然,以上所说的几步也只是一些简单的手段,如果考虑到不同平台之间的移植性就得做更多的#ifdef ...#define...#endif等成对的预处理了。OK!Enjoy your programming!