linux动态库(二)
来源:互联网 发布:mysql数据库备份还原 编辑:程序博客网 时间:2024/06/06 05:53
上篇文章呈现了linux下动态库的一个简单实现,其接口按通用的方式导出,测试程序可以直接调用,本篇展现一个导出函数列表的方式,可以通过函数列表实现对接口的调用
头文件
/* @ File Name: calc.h @ Author: hw @ Mail: feiyelove@163.com @ Created Time: 2015-07-01 14:42:00*/#ifndef _CALC_H_#define _CALC_H_#ifdef __cplusplusextern "C"{#endifint add(int a, int b);int sub(int a, int b);typedef struct _CALC_FUNCLIST { int version; int (*fnadd)(int a, int b); int (*fnsub)(int a, int b);}CALC_FUNCLIST;typedef CALC_FUNCLIST* CALC_FUNCLIST_PTR;typedef CALC_FUNCLIST_PTR* CALC_FUNCLIST_PTR_PTR;int GetFunclist(CALC_FUNCLIST_PTR_PTR ppFuncList);typedef void (*GET_FUNCLIST_PTR)(CALC_FUNCLIST_PTR_PTR ppFuncList);#ifdef __cplusplus} #endif #endif
源文件
/* @ File Name: calc.c @ Author: hw @ Mail: feiyelove@163.com @ Created Time: 2015-07-01 14:39:26*/#include "calc.h"#ifdef __cplusplusextern "C"{#endifint add(int a, int b){ return a + b;}int sub(int a, int b){ return a - b;}static CALC_FUNCLIST m_functionList ={ 0x01000001, // Version add, sub};int GetFunclist(CALC_FUNCLIST_PTR_PTR ppFuncList){ *ppFuncList = &m_functionList; return 0;}#ifdef __cplusplus}#endif
测试程序1
/* @ File Name: test1.c @ Author: hw @ Mail: feiyelove@163.com @ Created Time: 2015-07-01 17:50:16*/#include <stdio.h>#include <stdlib.h>#include "calc.h"int main(){ CALC_FUNCLIST_PTR pFuncList; GetFunclist(&pFuncList); printf("test add [ 1+2 = %d]\n", pFuncList->fnadd(1,2)); printf("test sub [ 1-2 = %d]\n", pFuncList->fnsub(1,2)); return 0;}
测试程序2
/* @ File Name: test2.c @ Author: hw @ Mail: feiyelove@163.com @ Created Time: 2015-08-25 09:49:41*/#include <stdio.h>#include <stdlib.h>#include <dlfcn.h>#include "calc.h"#define LIBNAME "./libcalc.so"int main(int argc, char *argv[]){ void *handle; int (*pFunc)(int,int); CALC_FUNCLIST_PTR pFuncList; GET_FUNCLIST_PTR ppFuncList; handle = dlopen(LIBNAME, RTLD_NOW); if (handle == NULL) { printf("%s", dlerror()); return -1; } pFunc = dlsym(handle, "add"); printf("test add [ 1+2 = %d]\n",pFunc(1,2)); pFunc = dlsym(handle, "sub"); printf("test sub [ 1-2 = %d]\n",pFunc(1,2)); ppFuncList = (GET_FUNCLIST_PTR)dlsym(handle, "GetFunclist"); ppFuncList(&pFuncList); printf("test add [ 1+2 = %d]\n", pFuncList->fnadd(1,2)); printf("test sub [ 1-2 = %d]\n", pFuncList->fnsub(1,2)); dlclose(handle); return 0;}
Makefile
CC = gccCFLAGS =LDFLAGS = -shared -fPICINC = -I.LIBS = -ldlDLL = libcalc.soOBJS = calc.o.PHONY:allall:lib test1 test2lib:$(OBJS) $(CC) $(LDFLAGS) -o $(DLL) $(OBJS)$(OBJS):%.o:%.c $(CC) $(CFLAGS) $(INC) -c $< -o $@test1: $(CC) -o test1 test1.c $(DLL) test2: $(CC) -o test2 test2.c $(LIBS)clean: rm -f *.o rm -f $(DLL) test1 test2
编译动态库及测试程序
$ make
查看动态库的导出符号
$ nm -D libcalc.so 00000414 T GetFunclist w _Jv_RegisterClasses00001590 A __bss_start w __cxa_finalize w __gmon_start__00001590 A _edata00001598 A _end00000464 T _fini000002bc T _init000003fc T add00000407 T sub
可以看到,接口GetFunclist add sub都被成功导出,这儿我们将add sub接口也一并导出了,也可以只导出GetFunclist接口,这样的话可以实现对add sub接口的隐藏,当然这只是隐藏接口的一种方式,gcc还提供了一种方法,可以自定义导出函数接口,只需在在编译选项加上-Wl,–version-script=funclist.txt即可,funclist.txt有一定的格式,内部定义了你要导出的接口,如下
{global:add;sub;GetFunclist ;local:*;};
这样便可以自由定义导出接口了
好了,回归正题
执行测试程序1
$ ./test1 test add [ 1+2 = 3]test sub [ 1-2 = -1]
执行测试程序2
./test2 test add [ 1+2 = 3]test sub [ 1-2 = -1]test add [ 1+2 = 3]test sub [ 1-2 = -1]
上述测试程序1展示了函数列表的使用方法,测试程序2展示了动态库的动态加载及调用过程
注意:动态加载注意要加入链接参数-ldl
0 0
- linux动态库(二)
- Linux动态链接库同名符号装载问题(二)
- Linux动态库原理(二)重定位
- Linux动态库原理(二)重定位
- Linux编程练习(二)—— Linux下.so动态库的建立和调用
- 动态链接库(二)
- Windows系统和Linux系统中的静态链接库与动态链接库(二)
- Linux下GCC生成和使用静态库和动态库详解(二)
- linux学习之二十六---动态链接库
- linux动态链接库的编译及使用<二>
- c++动态库(二)NoMFC动态库
- Linux 静态链接库与动态链接库之二:动态链接库生成及使用
- Linux 静态链接库与动态链接库之二:动态链接库生成
- Linux 静态链接库与动态链接库之二:动态链接库生成
- Windows动态库管理(二)
- C++动态链接库(二)
- 动态规划(二)
- 动态规划(二)
- Codevs3162抄书问题题解
- java web开发 高并发处理
- 软件测试工程的思路、方法、原则、
- 函数调用方式小结
- 【JavaScript】--原型
- linux动态库(二)
- IEEE 802.11ac 无线协议
- arm-linux-gdb+gdbserver环境搭建以及远程调试 及调试core文件
- [leetcode] 94.Binary Tree Inorder Traversal
- hdu 5120
- OpenVPN
- LXC1.0.7-- lxc-start 源码分析 01
- tinyxml编译学习笔记
- Android上下文菜单,长按出现的菜单