LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1335|回复: 8

在linux下如何创建自己的函数库?

[复制链接]
发表于 2007-4-18 10:41:41 | 显示全部楼层 |阅读模式
想建个函数库,把自己常用的一些函数包括进去,在使用时include一下就行了,应该怎么构建?
另外,我看到常用的一些函数库,如math.h,里面只有一些函数的声明,那么执行部分在哪里?又是如何实现调用的?初学编程,谢谢各位了!
发表于 2007-4-18 10:47:00 | 显示全部楼层
自己写个 .c 文件,再写个.h 文件,就行了。
把它们放在相对稳定的目录下。以后常调用就方便了。
这就是你自己的了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-4-18 10:51:43 | 显示全部楼层
能否说得祥细些?.c文件和.h文件名称是要一样吗?还有,在调用时是不是在程序里include那个.h文件就行了?
回复 支持 反对

使用道具 举报

发表于 2007-4-18 10:56:55 | 显示全部楼层
关于如何写 .c and .h file 你没看过书吗?我记得里面有讲的。任何一本关于C语言的书。
一般来讲文件名是一样的。方便自己记忆和他人阅读。
在C文件里写出函数的内容。
在H文件里声明函数。
调用你理解的是对的。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-4-18 11:19:19 | 显示全部楼层
还是有个问题,我写了一个first.c和first.h,里面包含了right和wrong函数,然后在主函数main里面include了first.h,编译main之后提示right和wrong函数找不到。请问应该怎么解决?我太弱了,还请不要嫌麻烦,谢谢了
回复 支持 反对

使用道具 举报

发表于 2007-4-18 11:39:01 | 显示全部楼层
楼主最好去找些书系统地读一读,至少,找一些代码看一看。

这里简要为楼主解释一下 .h 和 .c 一般情况下的作用

.c 是真正实现函数的东东,.h 负责提供接口,也就是声明。编译过程分为编译和连接,简单地说,.h 在编译时提供函数的声明,而 .c 编译成的 .o 目标文件则在连接时提供具体的实现
回复 支持 反对

使用道具 举报

发表于 2007-4-18 12:45:39 | 显示全部楼层
按你刚才说的编了个小程序,main.c 、first.h、first.c,在main.c里面包括了first.h,可编译时还是提示找不到first.h里面声明的函数,要把main.c和first.c一起编译才可以,这是为什么呢?


楼主问问题最好还是在论坛里,信息里问我如果不回话的话你就白问了。
在这里问,还有其它朋友会告诉你的。

你没有找到是因为你没有指定 .c .h 的路径。计算机当然是找不到的。
回复 支持 反对

使用道具 举报

发表于 2007-4-18 12:46:12 | 显示全部楼层
我自己以前写的一点东西.可能对你有用吧!

如何为Linux增加库
一.        静态库
在Linux下的静态库是以.a为后缀的文件。
1.        建静态库
h1.c 源文件
#include<stdio.h>
void hello1()
{
        printf(“the first hello!\n”);
}
h2.c 源文件
#include<stdio.h>
void hello2()
{
        printf(“the second hello!\n”);
}
2.主程序
hello.c 源文件
#include<stdio.h>
int main()
{
        hello1();
        hello2();
        return 0;
}
输入命令:
gcc –c h1.c
gcc –c h2.c
ar –r libhello.a h1.o h2.o
ar –s libhello.a
ranlib libhello.a
最后再
gcc –static hello.c –L. –lhello –o hello即可生成可执行文件。注意要使用-static参数,否则生成的仍然是动态类型的文件,不过对于hello这个库则是采用静态方式来使用的而已。
二.        动态库
1.建动态库
#include<stdio.h>
void hello1()
{
        printf(“the first hello!\n”);
}
h2.c 源文件
#include<stdio.h>
void hello2()
{
        printf(“the second hello!\n”);
}
2.        主程序
hello.c 源文件
#include<stdio.h>
int main()
{
        hello1();
        hello2();
        return 0;
}
输入命令:
gcc –fPIC –g –c h1.c –o libh1.o
gcc –fPIC –g –c h2.c –o libh2.o
gcc –g –shared –W1 –o libh1.so libh1.o –lc
gcc –g –shared –W1 –o libh2.so libh2.o –lc
然后再将主程序与库相连进行编译
gcc –g hello.c –o hello –L. –lh1 –lh2
最后再将当前路径放到库查找路径中去
export LD_LIBRARY_PATH=.LD_LIBRARY_PATY
最后再执行./hello即可运行。
三.        动态库的查找过程
一旦连接器完成了自己的初始化工作,就查找程序所需要的库的名字。程序头中有一个指针指向dynamic段,它包含了动态连接的信息,dynamic段中的DT_STRTAB指向一个字符表,而其中的DT_NEEDED包含了一个相对于字符表的偏移,指向所需要的库名。
对于每一个库,连接器首先查找库文件位置,从本质上说是一个相当复杂的过程。DT_NEEDED所描叙的库文件名一般类似libXt.so.6 (Xt开发包, 版本6),库文件可能在任意的库文件目录中,还也可能有重名的文件。在我的系统中,这个库的实际文件名是/usr/X11R6/lib/libXt.so.6.0,最后的“.0”表示次版本号。

连接器查找下列几个地方:

        首先查看 .dynamic 段是否包含了一个叫DT_RPATH的项(它是一个以冒号分隔的库文件搜索目录列表)。这个项是在程序被连接器连接时,由命令行开关或者环境变量添加上去的。它常应用于子系统中,比如像数据库应用,我们要装载一些程序集合以及支持库到一个目录中去的时候。

        查看是否存在环境变量 LD_LIBRARY_PATH(它是一个以冒号分隔的库文件搜索目录列表)。这个项可以帮助开发者建立一个新版本的库,把他的路径添加到LD_LIBRARY_PATH中,把它和现存的可连接程序一同使用,用来测试新的库,

        连接器查看库高速缓存文件 /etc/ld.so.conf ,它包含了库名和路径的一个对应列表,如果库名存在,连接器就使用它对应的路径,用这个查找方法能够找到大部分的库(文件名不需要和要求完全符合,这点可以参考接下来的“库的版本”)。

        如果上叙的查找都失败,连接器就查找默认路径 /usr/lib ,如果库文件依旧没有找到,则显示一个错误然后退出。

连接器找到了库文件后,先打开它,然后读取ELF头,找到指向各个段的指针。连接器为库的代码段和数据段分配空间并映射到内存,随后是bss(不分配空间)。.通过库的 .dynamic 段,连接器添加这个库的符号表到符号表链,如果库所依赖的其它库没有装载的话,则添加那个库到装载队列中。

完成这个过程后,所有的库都已经被映射,loader在逻辑上拥有了一个全局的符号表,它是全部程序和被映射库的符号表的联合。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-4-21 09:21:41 | 显示全部楼层
谢谢大家了!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表