SIPP 尚不支持compress , 但是已经列入计划,代码中也留好了调用动态链接库的接口。
+++++++++++++++++++++++++++++++++++++++
#define COMP_MAIN
#include "comp.h"
#include <dlfcn.h>
#include <string.h>
char * comp_load()
{
void *handle;
char *error;
comp_error[0] = 0;
handle = dlopen(COMP_PLUGGIN, RTLD_LAZY);
if (!handle)
{
strcpy(comp_error, dlerror());
return comp_error;
}
*(void **)(&comp_compress) = dlsym(handle, "comp_compress");
if((error = (char *) dlerror()))
{
strcpy(comp_error, error);
return comp_error;
}
*(void **)(&comp_uncompress) = dlsym(handle, "comp_uncompress"); if((error = (char *) dlerror()))
{
strcpy(comp_error, error);
return comp_error;
}
*(void **)(&comp_free) = dlsym(handle, "comp_free");
if((error = (char *) dlerror()))
{
strcpy(comp_error, error);
return comp_error;
}
return 0;
}
+++++++++++++++++++++++++++++++++++++
下面是对某些知识点的解释,转自其他文章,
相关函数的说明如下:(1)dlopen()第一个参数:指定共享库的名称,将会在下面位置查找指定的共享库。-环境变量LD_LIBRARY_PATH列出的用分号间隔的所有目录。-文件/etc/ld.so.cache中找到的库的列表,用ldconfig维护。-目录usr/lib。-目录/lib。-当前目录。第二个参数:指定如何打开共享库。其中flag有:RTLD_LAZY RTLD_NOW RTLD_GLOBAL,其含义分别为:RTLD_LAZY: 在dlopen返回前,对于动态库中存在的未定义的变量(如外部变量extern,也可以是函数)不执行解析,就是不解析这个变量的地址。RTLD_NOW :与上面不同,他需要在dlopen返回前,解析出每个未定义变量的地址,如果解析不出来,在dlopen会返回NULL,错误为:: undefined symbol: xxxx.......RTLD_GLOBAL: 它的含义是使得库中的解析的定义变量在随后的随后其它的链接库中变得可以使用。(2)dlsym()调用dlsym时,利用dlopen()返回的共享库的phandle以及函数名称作为参数,返回要加载函数的入口地址。(3)dlerror()该函数用于检查调用共享库的相关函数出现的错误。gcc -fpic -shared -o libstr.so Strlen.c Strnlen.c-fpic 使输出的对象模块是按照可重定位地址方式生成的。-shared 指定把对应的源文件生成对应的动态链接库文件libstr.so文件。nm 命令
nm命令可以列出一个函数库文件中的符号表。它对于静态的函数库和共享的函数库都起作用。对于一个给定的函数库,nm命令可以列出函数库中定义的所有符号,包括每个符号的值和类型。还可以给出在原程序中这个函数(符号)是在多少行定义的,不过这必须要求编译该函数库的时候加“-l”选项。
关于符号的类型,这里我们再多讨论一下。符号的类型是以一个字母的形式显示的,小写字母表示这个符号是本地(local)的,而大写字母则表示这个符号是全局的(global,externel)。一般来说,类型有一下几种:T、D、B、U、W。各自的含义如下:T表示在代码段中定义的一般变量符号;D 表示时初始化过的数据段;B表示初始化的数据段;U表示没有定义的,在这个库里面使用了,但是在其他库中定义的符号;W,weak的缩写,表示如果其他函数库中也有对这个符号的定义,则其他符号的定义可以覆盖这个定义。
如果你知道一个函数的名字,但是你不知道这个函数在什么库中定义的,那么可以用mn的“-o”选项和grep命令来查找库的名字。-o选项使得显示的每一行都有这个函数库文件名。例如,你要查找“cos”这个是在什么地方定义的,大致可以用下面的命令:
nm -o /lib/* /usr/lib/* /usr/lib/*/* /usr/local/lib/* 2> /dev/null
| grep 'cos$'
关于nm的更详细的用法我们可以参考info文档,位置是info:binutils#nm。
特殊函数_init和_fini
函数库里面有两个特殊的函数,_init和_fini,这个我们在前面已经说过了。主要是分别用来初始化函数库和关闭的时候做一些必要的处理,我们可以把自己认为需要的代码放到这两个函数里面,它们分别在函数库被加载和释放的时候被执行。具体说,如果一个函数库里面有一个名字为“_init”的函数输出,那么在第一次通过dlopen()函数打开这个函数库,或者只是简单的作为共享函数库被打开的时候,_init函数被自动调用执行。与之相对应的就是 _fini函数,当一个程序调用dlclose()去释放对这个函数库的引用的时候,如果该函数库的被引用计数器为0了,或者这个函数库是作为一般的共享函数库被使用而使用它的程序正常退出的时候,_fini就会被调用执行。C语言定义它们的原型如下:
void _init(void); void _fini(void);
当用gcc编译源程序为“.o”文件的时候,需要加一个“-nostartfiles”选项。这个选项使得C编译器不链接系统的启动函数库里面的启动函数。否则,就会得到一个“multiple-definition”的错误。
SIPP 代码学习笔记1- compress
最新推荐文章于 2021-06-18 17:57:06 发布