【 在 irene (yoyo) 的大作中提到: 】
: 如题
呵呵当然有,window那套动东东很多机制都是抄unix的
比如system(32)\*.dll是就是仿照unix的/usr/lib/*.so
unix的/usr/lib/*.so就是unix的动态库(dynamic library)
给程序动态链接用的,反之/usr/lib/*.a是静态库,程序编译
链接时就将相关函数链入目标文件。
实际上泥cc -o yyy yyy.o -lxxx那个xxx就是告诉cc找/usr/lib/libxxx.so..
yyy.o声明调用了libxxx.so中的函数,链接成功的目标文件yyy在运行时将动态
调用libxxx.so的函数,至于cc -o yyy yyy.o libxxx.a那就不同了呵呵
cc对-l参数的缺省链接方式是动态链接,即只链接符号,不链入函数实体。
对链接方式可man ld。
言归正传,既然有动态库,就肯定有与之相关的函数,window有loadlibrary,
偶solaris有dlopen,就是dynamic library open,window能让泥做
土版dll,偶solaris早就能让泥自己生产.so了呵呵,下面具体说明怎样调用
动态库libxxx里的函数而又不需要在cc中指定-lxxx。
首先是dlopen,格式:
#include
void * dlopen(const char *pathname, int mode);
返回一个void *类型的handle,否则返回null。
pathname就是泥所要打开的动态库,如果这个库声明链接了其它库,即对其它
库有依赖关系,那么所有相关有依赖关系的库都会被打开,这些打开的库称之
为组(group)。
mode是打开方式:
rtld_lazy:打开动态库后只重定位库中数据地址引用而不重定位而函数引用,
函数引用在该函数要被激活时才定位,的确lazy呵呵,但省开销;)
rtld_now: 与上者相比,动态库一被打开就重定位所有函数的引用。
rtld_global:打开动态库里的全局符号可以被其它所有库重定位。
rtld_local: 打开动态库里的全局符号只能被同组库重引用。
rtld_group: 只有相关组的符号才允许重定位??
rtld_parent:发dlopen调用的对象中的符号对被dlopen对象可见。
rtld_world: 。。。呵呵太晦涩了我翻译的我都看不明白;(
总之,一个rtld_lazy已经够用了呵呵;)
然后是得到重定位的数据或函数引用:
#include
void *dlsym(void *handle, const char *name)
意义明显,handle即dlopen的返回值,name即泥要引用的在动态库变量或函
数名称。成功返回重定位后的符号地址,失败返回null。
最后是关闭动态库:int dlclose(void *handle),
一看就明白,懒得解释了;)
下面给一个例子增加感性认识,该例子调用动态库client.so中的函数
int client_request(char *),该函数返回0或-1并根据不同错误设置
字符串err_info(也定义在client.so中):
# include
# include
# include
# define true 0
# define false -1
main( )
{
char buf[64];
void *handle; /* 动态库句柄 */
char *err_info; /* 要引用的动态库中的一个变量 */
int (*client_request)(char *); /* 要引用的一个函数 */
/* 打开动态库client.so */
if ((handle = dlopen("client.so", rtld_lazy)) == null) {
perror("dlopen");
exit(-1);
}
/* 得到函数名client_request的引用 */
if ((client_request =
(int (*)(char *))dlsym(handle, "client_request")) == null) {
perror("dlsym client_request");
exit(-1);
}
/* 得到变量名err_info的引用 */
if ((err_info =
(char *)dlsym(handle, "err_info")) == null) {
perror("dlsym err_info");
exit(-1);
}
for(;;) {
gets(buf); /* 从标准输入读入命令串 */
if (strcmp(buf, "exit") == true) {
dlclose(handle); /* 关闭动态库 */
return 0;
}
printf("request:%s\n", buf);
client_request(buf); /* 调用动态库中的函数 */
printf("ask: %s\n", err_info); /* 引用动态库中的变量 */
}
}
最后是编译问题,怎样编译成.so文件呢?很简单用ld或者cc -g就可以了,比如:
cc -g yyy.so yyy.o others.o -ldl
如果这个yyy.o有引用了其它动态库的函数呢?那么用cc -g ... -l了
比如yyy.o引用了socket函数,那么
cc -g yyy.so yyy.o others.o -ldl -lsocket即可。
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器