动态库是Linux下常用的一种共享库,与静态库不同,它在程序运行时才会被载入内存,并在程序退出时卸载,因此相比静态库可以节省内存空间。动态库有很多种类型,例如共享目标文件(.so)和动态链接库(.dll)等。C语言支持通过调用动态库中的函数来实现代码重用,本文将简单介绍如何在Linux下使用C语言调用动态库。
一、动态库的创建
在Linux下创建动态库的方法如下:
$ gcc -shared -o libtest.so test.c
其中,-shared指示编译器生成一个共享目标文件,-o指示输出文件名为libtest.so,test.c为源码文件名。
二、C语言调用动态库
为了调用动态库中的函数,需要在C程序中声明函数的原型,并使用dlopen()、dlsym()和dlclose()等系统调用来打开、查找和关闭动态库。
首先声明函数原型,例如test.c中定义了一个名为test()的函数:
“`c
#include
void test()
{
printf(“Hello, World!\n”);
}
“`
然后,在调用test()函数之前,需要使用dlopen()函数来打开动态库,并将其句柄存储在一个void类型的指针中:
“`c
#include
int mn()
{
void* handle = dlopen(“./libtest.so”, RTLD_LAZY);
if (!handle)
{
printf(“%s\n”, dlerror());
return 1;
}
typedef void (*func_t)();
func_t func = (func_t)dlsym(handle, “test”);
if (!func)
{
printf(“%s\n”, dlerror());
return 1;
}
func();
dlclose(handle);
return 0;
}
“`
在上述代码中,我们首先使用dlopen()函数打开了名为libtest.so的动态库,如果打开失败则输出错误信息,并退出程序。然后,使用dlsym()函数查找名为test的函数,并将其转换为一个函数指针,最后通过函数指针调用test()函数。需要注意的是,dlsym()函数会返回一个void指针,需要将其显式转换为正确的函数指针类型。使用dlclose()函数关闭动态库句柄。
三、完整示例代码
test.c:
“`c
#include
void test()
{
printf(“Hello, World!\n”);
}
“`
mn.c:
“`c
#include
#include
int mn()
{
void* handle = dlopen(“./libtest.so”, RTLD_LAZY);
if (!handle)
{
printf(“%s\n”, dlerror());
return 1;
}
typedef void (*func_t)();
func_t func = (func_t)dlsym(handle, “test”);
if (!func)
{
printf(“%s\n”, dlerror());
return 1;
}
func();
dlclose(handle);
return 0;
}
“`
编译:
$ gcc -shared -o libtest.so test.c
$ gcc -o mn mn.c -ldl
运行:
$ ./mn
Hello, World!
四、
相关问题拓展阅读:
- linuxopencv生成的静态或动态库怎样在调用的时候不用安装openvcv环境
- linux调用动态库弹出界面
- 关于linux下连接动态库问题
linuxopencv生成的静态或动态库怎样在调用的时候不用安装openvcv环境
使用cmake编译opencv静态链接库(静态库),配置环境变量(动态库和静态库一样),复制dll文件。
将这三个dll分别复制到C:\Windows\System32和C:\Windows\SysWOW64目录下。
配置包含目录升悄运:视图->其它窗口->属性管理器。运李配置库目录然吵梁后配置附加依赖项。
linux调用动态库弹出界面
您想问的是动态库的罩搜显式调用吧。
首先打开一个新库,并把它装入内存。如搜
dlopen在dlfcn.h中定义,并在dl库中实现。
当库被装入后,可以把dlopen返回的句柄作为给dlsym的之一个参数,以渣闷历获得符号在库中的地址。
关于linux下连接动态库问题
/etc/ld.so.conf 里或者环境高闭变山搜量里添加库路径,或者要戚唯裂把文件放到/usr/lib这样的路径里面,再更新一下ld.so.conf文件
gcc编译时,当使用动态库编译可以按照几种写法
1.gcc test.c ./libSDL2-2.so
2.gcc test.c -lSDL2-2
3.gcc test.c -L/home/test -lSDL2-2
一般的编译参数都是按照2或3去写
2写法的含义是从/lib或者/usr/lib目录下寻找名称为SDL2-2的库,即寻找/lib/libSDL2-2.so或者/usr/lib/libSDL2-2.so文件进行链接,当然如果没有动态库升咐就会去找静态库,再没有应该就会在编译时报错
3写法的含义是从-L参数首先从指定的目录中寻找需要链接的库文件,随后再去寻找系统文件夹中是否存在需要的库
1写法的含义是将当前目录下的./libSDL2-2.so.0文件链接进最终文件,因此执行readelf -a a.out后在动态库部分所看到的路径就是./libSDL2-2.so.0,进而在执行文件时仅会从当前目录下寻找libSDL2-2.so.0文件,当执行文件时所在的目录下没有该文件时就会出现找不到库文件的操作吵困纯
你第二次操作时,因为function.so库文件与a.out文件在同一个目录,同时也是在该目录下执行的ldd操作及运行a.out,a.out在加载动态库时从当前目录下找到了所需要的库文件,此时能够执行成功(ldd命令实质是一个脚本,通过设置环境变量运行动态库链接器来输出所有待链接的动态库)。
你可以试试将a.out拷贝至其他目录再次运行,将出现和之一次操作时一样的现象,找不到function.so文件。
具体的解决方法就是修改编译参数,将./libSDL2-2.so.0修改为-lSDL2-2并将libSDL2-2.so.0文件拷贝至/usr/lib目录下,并且可能因为没有修改链接器的缓存文件(将可能找不到带版本号后缀的动态库),需要在/usr/lib目录下建立一个文件连接(ln -s libSDL2-2.so.0 libSDL2-2.so)或尺游者直接修改名称为libSDL2-2.so
很桥野奇怪的游消尘gcc用法, 链接库的时候你应该神禅使用选项”-l”来指定, 而不是像个c文件一样直接写在后面.
关于linux c调用动态库的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。