首先由下面几个函数:strlen.h;strlen.c;strnlen.c;main.c
//strlen.h 头文件
int strnlen(char *pStr, unsigned long ulMaxLen);
int strlen(char *pStr);
//strlen.c 实现给定字符串的长度
#include<stdio.h>
#include<assert.h>
int strlen(char *pStr)
{
unsigned long ulLength;
assert(NULL != pStr);
ulLength = 0;
while(*pStr++)
{
ulLength++;
}
return ulLength;
}
//strnlen.c 获取给定字符串的长度,若输入字符串的长度大于指定的最大长度,则返回最大长度,否则返回字符串的实际长度。
#include<stdio.h>
#include<assert.h>
int strnlen(char *pStr, unsigned long ulMaxLen)
{
unsigned long ulLength;
assert(NULL != pStr);
if(ulMaxLen <= 0)
{
printf("Wrong Max length!/n");
return -1;
}
ulLength = 0;
while(*pStr++ && ulLength<ulMaxLen)
{
ulLength++;
}
return ulLength;
}
//main.c
#include"strlen.h"
#include<stdio.h>
int main(int argc, char *argv[])
{
char str[] = "hello world";
unsigned long ulLength = 0;
printf("The string is :%s/n", str);
ulLength = strlen(str);
printf("The string length is :%d(use strlen)/n", (int)ulLength);
ulLength = strnlen(str, 10);
printf("The string length is :%d(use strnLen)/n", (int)ulLength);
return 0;
}
第一种:生成静态库:gcc –c strlen.c strnlen.c (使用gcc生成对应的目标文件)
然后用ar创建一个名字为libstr.a的库文件,并把strlen.o and strnlen.o的内容插入到对应的库文件中。:ar –rc libstr.a strlen.o strnlen.o(命令成功后,对应的静态库libstr.a已经成功生成)
静态库的使用:gcc –c –I./ main.c(因为我的头文件strlen.h就在当前目录下,如果在别的目录,比如在/home/cc/strlen.h。则这样写gcc –c –l/home/cc main.c),现在就允许结果
第二种:生成动态库
Gcc –fpic –shared –o libstr.so strlen.c strnlen.c (-fpic 使输出的对象模块是按照可重定位地址方式生成的)(-shared 指定把对应的源文件生成对应的动态链接库文件libstr.so文件)
(动态库有两种,一个.so结尾的是隐式调用的动态库。调用dlopen函数的是显式调用的动态库)
隐式调用:
Gcc –c –I./ main.c
Gcc –o main1 –L./ main.o libstr.so
./main1
出现error while loading shared libraries: xxx.so.0:cannot open shared object file: No such file or directory。
解决办法:库文件在连接和运行时被使用,其搜索路径在系统中进行设置的。一般linux系统把/lib和/usr/lib两个目录作为默认的库搜索路径,所以使用这两个目录中的库时不需要进行设置搜索路径即刻直接使用。对于处于默认库之外的库,需要将库的位置(路径)添加到库的搜索路径之中。设置库文件的搜索路径有下列两种方式,可任选一种:
A 在环境变量Ld_LIBRARY_PATH中指明库的搜索路径。
B 在/etc/ld.so.conf文件中添加库的搜索路径。
注:第一种方法我没弄成功,看第二种。打开vi /etc/ld.so.conf 文件,#include /etc/ld.so.conf.d/*.conf(原文有的)换一行加上这个/network_programing/02(我的libstr.so在这个目录下面)保存退出。然后执行/sbin/ldconfig –v。从新gcc一次,运行./main1就出结果。
显示调用:
//main3.c
#include<stdio.h>
#include<dlfcn.h>
int main(int argc, char *argv[])
{
int (*pStrlenFun)(char *pStr);//声明对应得函数的函数指针。
int (*pStrnlenFun)(char *pStr, int ulMaxLen);
char str[] = "hello world";
unsigned long ulLength = 0;
void *pdlHandle;
char *pszErr;
pdlHandle = dlopen("./libstr.so", RTLD_LAZY);//加载链接库/libstr.so
if(!pdlHandle)
{
printf("Failed load library/n");
}
pszErr = dlerror();
if(pszErr != NULL)
{
printf("%s/n", pszErr);
return 0;
}
pStrlenFun = dlsym(pdlHandle, "strlen");//获取函数的地址
pszErr = dlerror();
if(pszErr != NULL)
{
printf("%s/n", pszErr);
return 0;
}
pStrnlenFun = dlsym(pdlHandle, "strnlen");
pszErr = dlerror();
if(pszErr != NULL)
{
printf("%s/n", pszErr);
return 0;
}
printf("The string is:%s/n", str);
ulLength = pStrlenFun(str);//调用相关的函数
printf("The string length is:%d(use strlen)/n",(int)ulLength);
ulLength = pStrnlenFun(str, 10);
printf("the string length is:%d(use strnlen)/n", (int)ulLength);
dlclose(pdlHandle);
return 0;
}
Gcc –o main3 –ldl main3.c
注意:用gcc编译对于的源文件生成可执行文件,-ldl选项,表示生成的对象模块需要使用共享库。执行对应的文件同样可以得到正确的结果。
dlsym()的函数原型是
void* dlsym(void* handle,const char* symbol)
该函数在<dlfcn.h>文件中。 handle是由dlopen打开动态链接库后返回的指针,symbol就是要求获取的函数的名称,函数返回值是void*,指向函数的地址,供调用使用。
dlopen() 功能:打开一个动态链接库
包含头文件: #include <dlfcn.h>
函数定义: void * dlopen( const char * pathname, int mode );
函数描述: 在dlopen的()函数以指定模式打开指定的动态连接库文件,并返回一个句柄给调用进程。使用dlclose()来卸载打开的库。
mode:分为这两种
RTLD_LAZY 暂缓决定,等有需要时再解出符号
RTLD_NOW 立即决定,返回前解除所有未决定的符号。
RTLD_LOCAL
RTLD_GLOBAL 允许导出符号
RTLD_GROUP
RTLD_WORLD
返回值: 打开错误返回NULL 成功,返回库引用 编译时候要加入 -ldl (指定dl库)
const char *dlerror(void);
函数描述: 当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。