linux下动态链接的例子有很多,我从网上找到了一个,如下
动态链接示例地址:
https://blog.youkuaiyun.com/fuyuande/article/details/82913961
对于main函数,我稍微修改了下,添加了printf打印一些地址
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>
void main()
{
void *handle;
void (*hello)(void);
/* 加载libHelloWorld.so */
handle = dlopen("libHelloWorld.so", RTLD_LAZY);
if (!handle)
{
printf("open libHelloWorld.so fail\r\n");
return;
}
printf("handle is %p\n", handle);
/* 引用库提供的symbol,可以是变量也可以是函数 */
hello = dlsym(handle, "hello");
if ( !hello )
{
printf("open symbol fail\r\n");
dlclose(handle);
return;
}
printf("address of hello function is %p\n", hello);
/* 调用库函数 */
hello();
while(1);
/* 释放库的引用计数 */
dlclose(handle);
return;
}
控制台输出的结果如下:
[root@localhost learn]# ./dllib
handle is 0x152a040
address of hello function is 0x7f1898c09665
Hello World
从上面的运行结果看,很明显,是64位的进程。
在windows操作系统下,与dlopen对应的是LoadLibrary函数,LoadLibrary返回的是dll加载于进程虚拟地址空间的地址,具有非常明确的含义。但是linux下的dlopen返回的handle是0x152a040,这个很明显,不是so加载到进程虚拟地址空间的地址。
此进程号为16492,我们使用命令cat /proc/16492/maps,打印结果如下
此处,我们加载的动态库是libHelloWorld.so,从图中可以看出此动态库加载到进程地址空间的起始地址是7f1898c09000,这个与main函数中打印出的hello函数的地址0x7f1898c09665非常接近,差了一个0x665,这个0x665实际上就是hello函数在动态库libHelloWorld.so里面的偏移地址,可以从nm命令验证这一点,如下所示:
[root@localhost learn]# nm libHelloWorld.so |grep hello
0000000000000665 T hello
所以,跟windows一样,动态库里面函数在内存空间的地址,其实就是动态库在进程空间的地址+此函数在动态库里面的偏移地址。
下面给出动态库libHelloWorld.so的头文件和.c文件代码,以免上面的链接丢失
//实现文件 HelloWorld.c
/**
* 简单动态库文件使用
*/
#include "HelloWorld.h"
void hello(void)
{
printf("Hello World \r\n");
return ;
}
//头文件 HelloWorld.h
#include <stdio.h>
void hello(void);