将各个版本编译成动态库××.so,并提供统一的接口供调用。这里使用的工具是dlxx系列函数
例子
#
#
#
//海湾合作委员会标志
// gcc.c -ldl
整数
主要(int argc,字符**argv)
{
空白 *;
(*)();
字符*错误;
= ("libm.so", );
如果 (!) {
(, "%s\n", ());
出口();
}
();
*(void **) (&) = dlsym(, "cos");
if ((错误 = ()) != NULL) {
(, "%s\n", 错误);
出口();
}
("%f\n", (*)(0.0));
();
出口();
}
使用libdl库进行编译
gcc.c-ldl
输出
1.
利用技巧,编写基本框架,很容易实现一些公司提倡的dll编程
参考文章
=============================
浏览器用户非常熟悉插件的概念。 从网上下载插件,通常这些插件提供对浏览器的音频、视频和特效的增强支持。 一般来说,插件为现有应用程序提供新功能,而无需更改原始应用程序。
DLL 是在设计和构建应用程序时该程序已知的程序函数。 应用程序的主程序是使用程序框架或背板设计的,在运行时有选择地加载与主程序分开的磁盘文件中所需的dll。 这种打包和动态加载提供了灵活的升级、维护和许可策略。
Linux 附带了数千个命令和应用程序,所有这些命令和应用程序都至少需要 libc 库函数。 如果 libc 函数与每个应用程序一起打包,则磁盘上将会有数千个相同函数的副本。 Linux 构建这些应用程序时使用通常需要的系统库的单个系统级副本,而不会浪费磁盘空间。 Linux 做得更好。 每个需要公共系统库函数的进程都使用单个系统级副本,该副本立即加载到内存中并由进程共享。
在 Linux 中,插件和 dll 被实现为动态库。 本文的其余部分是使用动态库在应用程序运行后更改应用程序的示例。
Linux 中的应用程序通过以下两种方式之一链接到外部函数:在构建时静态链接静态库 ( lib*.a ) 并将库代码包含在应用程序的可执行文件中; 或在运行时动态链接共享库 (lib*.so)。 通过动态链接加载器,动态库被映射到应用程序的可执行内存中。 在启动应用程序之前,动态链接加载器将所需的共享对象库映射到应用程序的内存中,或者使用系统共享对象并解析应用程序所需的外部引用。 该应用程序现在已准备好运行。
作为示例,下面是一个小程序,演示了 Linux 中动态链接库的默认使用:
主要的()
{
(“你好世界
”);
}
当使用 gcc 编译 hello.c 时,会创建一个名为 a.out 的可执行文件。 使用Linux命令ldda.out(打印出共享库相互依赖关系),可以看出需要的共享库是:
libc.so.6 => /lib/libc.so.6 ()/lib/ld-linux.so.2 => /lib/ld-linux.so.2 ()
在应用程序运行后,使用相同的动态链接加载器将dll映射到应用程序的内存中。 通过使用Linux动态加载例程,应用程序控制加载哪个动态库以及调用库中的哪个函数来执行加载和链接并返回所需入口点的地址。
Linux 提供了 4 个库函数( 、 、 dlsym 和 )、一个文件( dlfcn.h )和两个共享库(静态库 libdl.a 和动态库 libdl.so )来支持动态链接加载器。 这些库函数是:
动态链接加载程序需要在文件系统中查找共享对象文件以打开该文件并创建句柄。 有 4 种方法可以指定文件的位置:
动态链接加载器示例程序是一个小型 C 程序,旨在练习 dl 例程。 该程序基于每个人都编写的 C 程序,该程序将“”打印到控制台。 最初打印的消息是“”。 测试程序链接到两个再次打印消息的函数:第一次使用大写字符,第二次使用小写字符。
以下是该计划的概要:
定义 dll 文件 dlfcn.h 和所需的变量。 至少需要这些变量:打印初始消息“HeLlO WoRlD”。 使用绝对路径“/home//.so”和选项,打开dll的共享对象文件并返回句柄。 dlsym 返回入口点的地址。
调用并打印修改后的消息“HELLO WORLD”。 关闭 .so 的句柄并从内存中取消 dll 的映射。
根据环境变量使用相对路径找到共享对象路径,打开dll的共享对象文件.so,并返回句柄。
dlsym 返回入口点的地址。
调用并打印修改后的消息“hello world”。 关闭 .so 的句柄并从内存中取消 dll 的映射。
请注意,在每次调用 dlsym 或更高版本之后,调用以获取最后一条错误消息并打印该错误消息字符串。 这是测试运行:
2- HeL1O 3- 使用路径打开 -(null)- 4-查找 -(null)- HELLO 5- -(null)- 6-关闭 -(null)- 7- 使用路径打开 -(null)- 8-查找-(空)- 你好 9- -(空)- 10-关闭 -(空)-
本文后面列出了完整的 .c、.c 和 .c 源代码列表。
启用运行时动态链接需要三个步骤:
将dll编译为与位置无关的代码创建dll共享对象文件编译主程序并将其与dl库链接
编译 .c 和 .c 的 gcc 命令包含 -fpic 选项。 选项 -fpic 和 -fPIC 导致生成的代码与位置无关,这是重建共享对象库所必需的。 -fPIC 选项生成支持大偏移量的与位置无关的代码。 .o 和 .o 的第二个 gcc 命令带有 - 选项,生成适合动态链接的共享对象文件 a*.so。
编译执行的ksh脚本如下:
#!/bin/ksh
#建造
#
#设置-x
清除
#
# 用于路径测试
#
如果[-f.o]; 然后 rm.o
该网络
gcc -c -fpic.c
如果 [ -f .so ]; 然后 rm .so
该网络
gcc - -lc -o .so .o
#
# 用于路径测试
#
= `密码`
如果[-f.o]; 然后 rm.o
该网络
gcc -c -fpic.c
如果 [ -f .so ]; 然后 rm .so
该网络
gcc - -lc -o .so .o
#
# 测试
#
如果[-f]; 然后 rm
该网络
gcc-oc-ldl
回声= $
创建可以在运行时动态链接到 Linux 系统上的应用程序的共享对象代码是一项非常简单的练习。 应用程序通过使用 dlsym 和对动态链接加载器的函数调用来访问共享对象。 以字符串形式返回任何错误,描述 dl 函数遇到的最后一个错误。 在运行时,主应用程序使用绝对路径或相对路径查找共享对象库,并请求所需的 dll 入口点的地址。 当需要时,还可以对dll进行间接函数调用,最后关闭共享对象文件的句柄,并从内存中取消对象文件的映射,使其无法使用。
使用附加选项 -fpic 或 -fPIC 编译共享对象代码以生成与位置无关的代码,并使用 - 选项将对象代码放入共享对象库中。
Linux 中的共享目标代码库和动态链接加载器为应用程序提供了附加功能。 减少了磁盘和内存中的可执行文件大小。 可以根据需要加载可选的应用程序功能,可以在不重建整个应用程序的情况下修复缺陷,并且应用程序可以包含第三方插件。
#
#
#
void *;
int (*)();
const char *;
主要( argc , argv )
{
int rc;
char[] = "HeLlO WoRlD\n";
("2-\n");
(“%s”,);
= ("/home//.so",);
= ();
("3-使用路径-%s-\n打开", );
如果()退出(1);
= dlsym( , "" );
= ();
("4-查找-%s-\n", );
如果()退出(1);
rc = (*)( );
("5- -%s- \n", );
rc = ();
= ();
("6-关闭-%s-\n",);
if( rc ) 退出(1);
= (".so",);
= ();
("7-使用路径-%s-\n打开", );
如果()退出(1);
= dlsym( , "" );
= ();
("8-查找-%s-\n", );
如果()退出(1);
rc = (*)( );
("9- -%s- \n", );
rc = ();
= ();
("10-关闭-%s-\n",);
if( rc ) 退出(1);
(0);
}
整型 ( )
字符[];
{
字符[256];
字符 *inptr, *;
输入指针 = ;
= ;
while ( *inptr != '\0' )
*++ = (*inptr++);
*++ = '\0';
();
(1);
}
整型 ( )
字符[];
{
字符[256];
字符 *inptr, *;
输入指针 = ;
= ;
while ( *inptr != '' )
*++ = (*inptr++);
*++ = '';
();
(2);
}
=============================
参考
为 Linux 应用程序编写 DLL 的人
阅读 (1241) | 评论 (0) | 转发 (0) |